Browse Source

Fixed map functions. Update map helps.

pull/5422/head
Igor Kulikov 5 years ago
parent
commit
3d52420d17
  1. 30
      ui-ngx/src/app/core/api/data-aggregator.ts
  2. 55
      ui-ngx/src/app/modules/home/components/widget/lib/maps/common-maps-utils.ts
  3. 60
      ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts
  4. 10
      ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts
  5. 4
      ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.html
  6. 43
      ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts
  7. 6
      ui-ngx/src/assets/help/en_US/widget/lib/map/map_fn_args.md
  8. 2
      ui-ngx/src/assets/help/en_US/widget/lib/map/path_color_fn.md
  9. 2
      ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_color_fn.md
  10. 4
      ui-ngx/src/assets/help/en_US/widget/lib/map/tooltip_fn.md
  11. 11
      ui-ngx/src/assets/help/en_US/widget/lib/map/trip_fn_args.md
  12. 40
      ui-ngx/src/assets/help/en_US/widget/lib/map/trip_label_fn.md
  13. 62
      ui-ngx/src/assets/help/en_US/widget/lib/map/trip_marker_image_fn.md
  14. 2
      ui-ngx/src/assets/help/en_US/widget/lib/map/trip_point_as_anchor_fn.md
  15. 40
      ui-ngx/src/assets/help/en_US/widget/lib/map/trip_tooltip_fn.md

30
ui-ngx/src/app/core/api/data-aggregator.ts

@ -25,7 +25,7 @@ import {
SubscriptionTimewindow
} from '@shared/models/time/time.models';
import { UtilsService } from '@core/services/utils.service';
import { deepClone, isNumeric } from '@core/utils';
import { deepClone, isNumber, isNumeric } from '@core/utils';
import Timeout = NodeJS.Timeout;
export declare type onAggregatedData = (data: SubscriptionData, detectChanges: boolean) => void;
@ -92,20 +92,36 @@ declare type AggFunction = (aggData: AggData, value?: any) => void;
const avg: AggFunction = (aggData: AggData, value?: any) => {
aggData.count++;
aggData.sum += value;
aggData.aggValue = aggData.sum / aggData.count;
if (isNumber(value)) {
aggData.sum += value;
aggData.aggValue = aggData.sum / aggData.count;
} else {
aggData.aggValue = value;
}
};
const min: AggFunction = (aggData: AggData, value?: any) => {
aggData.aggValue = Math.min(aggData.aggValue, value);
if (isNumber(value)) {
aggData.aggValue = Math.min(aggData.aggValue, value);
} else {
aggData.aggValue = value;
}
};
const max: AggFunction = (aggData: AggData, value?: any) => {
aggData.aggValue = Math.max(aggData.aggValue, value);
if (isNumber(value)) {
aggData.aggValue = Math.max(aggData.aggValue, value);
} else {
aggData.aggValue = value;
}
};
const sum: AggFunction = (aggData: AggData, value?: any) => {
aggData.aggValue = aggData.aggValue + value;
if (isNumber(value)) {
aggData.aggValue = aggData.aggValue + value;
} else {
aggData.aggValue = value;
}
};
const count: AggFunction = (aggData: AggData) => {
@ -409,7 +425,7 @@ export class DataAggregator {
}
private convertValue(val: string): any {
if (!this.noAggregation || val && isNumeric(val) && Number(val).toString() === val) {
if (val && isNumeric(val) && (!this.noAggregation || this.noAggregation && Number(val).toString() === val)) {
return Number(val);
}
return val;

55
ui-ngx/src/app/modules/home/components/widget/lib/maps/common-maps-utils.ts

@ -16,7 +16,7 @@
import { FormattedData, MapProviders, ReplaceInfo } from '@home/components/widget/lib/maps/map-models';
import {
createLabelFromDatasource, deepClone,
createLabelFromDatasource,
hashCode,
isDefined,
isDefinedAndNotNull,
@ -127,7 +127,6 @@ export function aspectCache(imageUrl: string): Observable<number> {
export type TranslateFunc = (key: string, defaultTranslation?: string) => string;
const varsRegex = /\${([^}]*)}/g;
const linkActionRegex = /<link-act name=['"]([^['"]*)['"]>([^<]*)<\/link-act>/g;
const buttonActionRegex = /<button-act name=['"]([^['"]*)['"]>([^<]*)<\/button-act>/g;
@ -304,7 +303,8 @@ export const parseWithTranslation = {
if (this.translateFn) {
return this.translateFn(key, defaultTranslation);
} else {
throw console.error('Translate not assigned');
console.error('Translate not assigned');
throw Error('Translate not assigned');
}
},
parseTemplate(template: string, data: object, forceTranslate = false): string {
@ -334,7 +334,7 @@ export function parseData(input: DatasourceData[], dataIndex?: number): Formatte
if (!obj.hasOwnProperty(el.dataKey.label) || el.data[dataIndex][1] !== '') {
obj[el.dataKey.label] = el.data[dataIndex][1];
obj[el.dataKey.label + '|ts'] = el.data[dataIndex][0];
if (el.dataKey.label === 'type') {
if (el.dataKey.label.toLowerCase() === 'type') {
obj.deviceType = el.data[dataIndex][1];
}
}
@ -360,28 +360,35 @@ export function flatData(input: FormattedData[]): FormattedData {
}
export function parseArray(input: DatasourceData[]): FormattedData[][] {
return _(input).groupBy(el => el?.datasource?.entityName)
.values().value().map((entityArray) =>
entityArray[0].data.map((el, i) => {
const obj: FormattedData = {
entityName: entityArray[0]?.datasource?.entityName,
entityId: entityArray[0]?.datasource?.entityId,
entityType: entityArray[0]?.datasource?.entityType,
$datasource: entityArray[0]?.datasource,
dsIndex: i,
time: el[0],
deviceType: null
};
entityArray.filter(e => e.data.length && e.data[i]).forEach(entity => {
obj[entity?.dataKey?.label] = entity?.data[i][1];
obj[entity?.dataKey?.label + '|ts'] = entity?.data[0][0];
if (entity?.dataKey?.label === 'type') {
obj.deviceType = entity?.data[0][1];
return _(input).groupBy(el => el.datasource.entityName)
.values().value().map((entityArray, dsIndex) => {
const timeDataMap: {[time: number]: FormattedData} = {};
entityArray.filter(e => e.data.length).forEach(entity => {
entity.data.forEach(tsData => {
const time = tsData[0];
const value = tsData[1];
let data = timeDataMap[time];
if (!data) {
data = {
entityName: entity.datasource.entityName,
entityId: entity.datasource.entityId,
entityType: entity.datasource.entityType,
$datasource: entity.datasource,
dsIndex,
time,
deviceType: null
};
timeDataMap[time] = data;
}
data[entity.dataKey.label] = value;
data[entity.dataKey.label + '|ts'] = time;
if (entity.dataKey.label.toLowerCase() === 'type') {
data.deviceType = value;
}
});
return obj;
})
);
});
return _.values(timeDataMap);
});
}
export function parseFunction(source: any, params: string[] = ['def']): (...args: any[]) => any {

60
ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts

@ -474,9 +474,10 @@ export default abstract class LeafletMap {
this.showPolygon = showPolygon;
if (this.map) {
const data = this.ctx.data;
const formattedData = parseData(this.ctx.data);
const formattedData = parseData(data);
if (drawRoutes) {
this.updatePolylines(parseArray(data), false);
const polyData = parseArray(data);
this.updatePolylines(polyData, formattedData, false);
}
if (showPolygon) {
this.updatePolygons(formattedData, false);
@ -633,7 +634,8 @@ export default abstract class LeafletMap {
return polygon;
}
updatePoints(pointsData: FormattedData[][], getTooltip: (point: FormattedData) => string) {
updatePoints(pointsData: FormattedData[][],
getTooltip: (point: FormattedData, points: FormattedData[]) => string) {
if (pointsData.length) {
if (this.points) {
this.map.removeLayer(this.points);
@ -642,21 +644,25 @@ export default abstract class LeafletMap {
}
let pointColor = this.options.pointColor;
for (const pointsList of pointsData) {
pointsList.filter(pdata => !!this.convertPosition(pdata)).forEach(data => {
if (this.options.useColorPointFunction) {
pointColor = safeExecute(this.options.colorPointFunction, [data, pointsData, data.dsIndex]);
}
const point = L.circleMarker(this.convertPosition(data), {
color: pointColor,
radius: this.options.pointSize
});
if (!this.options.pointTooltipOnRightPanel) {
point.on('click', () => getTooltip(data));
} else {
createTooltip(point, this.options, data.$datasource, getTooltip(data));
for (let tsIndex = 0; tsIndex < pointsList.length; tsIndex++) {
const pdata = pointsList[tsIndex];
if (!!this.convertPosition(pdata)) {
const dsData = pointsData.map(ds => ds[tsIndex]);
if (this.options.useColorPointFunction) {
pointColor = safeExecute(this.options.colorPointFunction, [pdata, dsData, pdata.dsIndex]);
}
const point = L.circleMarker(this.convertPosition(pdata), {
color: pointColor,
radius: this.options.pointSize
});
if (!this.options.pointTooltipOnRightPanel) {
point.on('click', () => getTooltip(pdata, dsData));
} else {
createTooltip(point, this.options, pdata.$datasource, getTooltip(pdata, dsData));
}
this.points.addLayer(point);
}
this.points.addLayer(point);
});
}
}
if (pointsData.length) {
this.map.addLayer(this.points);
@ -665,15 +671,15 @@ export default abstract class LeafletMap {
// Polyline
updatePolylines(polyData: FormattedData[][], updateBounds = true, activePolyline?: FormattedData) {
updatePolylines(polyData: FormattedData[][], dsData: FormattedData[], updateBounds = true) {
const keys: string[] = [];
polyData.forEach((dataSource: FormattedData[]) => {
const data = activePolyline || dataSource[0];
if (dataSource.length && data.entityName === dataSource[0].entityName) {
polyData.forEach((tsData: FormattedData[], index) => {
const data = dsData[index];
if (tsData.length && data.entityName === tsData[0].entityName) {
if (this.polylines.get(data.entityName)) {
this.updatePolyline(data, dataSource, this.options, updateBounds);
this.updatePolyline(data, tsData, dsData, this.options, updateBounds);
} else {
this.createPolyline(data, dataSource, this.options, updateBounds);
this.createPolyline(data, tsData, dsData, this.options, updateBounds);
}
keys.push(data.entityName);
}
@ -689,9 +695,9 @@ export default abstract class LeafletMap {
});
}
createPolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings, updateBounds = true) {
createPolyline(data: FormattedData, tsData: FormattedData[], dsData: FormattedData[], settings: PolylineSettings, updateBounds = true) {
const poly = new Polyline(this.map,
dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings);
tsData.map(el => this.convertPosition(el)).filter(el => !!el), data, dsData, settings);
if (updateBounds) {
const bounds = poly.leafletPoly.getBounds();
this.fitBounds(bounds);
@ -699,10 +705,10 @@ export default abstract class LeafletMap {
this.polylines.set(data.entityName, poly);
}
updatePolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings, updateBounds = true) {
updatePolyline(data: FormattedData, tsData: FormattedData[], dsData: FormattedData[], settings: PolylineSettings, updateBounds = true) {
const poly = this.polylines.get(data.entityName);
const oldBounds = poly.leafletPoly.getBounds();
poly.updatePolyline(dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings);
poly.updatePolyline(tsData.map(el => this.convertPosition(el)).filter(el => !!el), data, dsData, settings);
const newBounds = poly.leafletPoly.getBounds();
if (updateBounds && oldBounds.toBBoxString() !== newBounds.toBBoxString()) {
this.fitBounds(newBounds);

10
ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts

@ -866,7 +866,7 @@ export const pathSchema =
'useColorFunction',
{
key: 'colorFunction',
helpId: 'widget/lib/map/trip_path_color_fn',
helpId: 'widget/lib/map/path_color_fn',
type: 'javascript',
condition: 'model.useColorFunction === true'
},
@ -961,7 +961,7 @@ export const pointSchema =
'useColorPointFunction',
{
key: 'colorPointFunction',
helpId: 'widget/lib/map/trip_path_point_color_fn',
helpId: 'widget/lib/map/path_point_color_fn',
type: 'javascript',
condition: 'model.useColorPointFunction === true'
},
@ -1150,7 +1150,7 @@ export const tripAnimationSchema = {
{
key: 'labelFunction',
type: 'javascript',
helpId: 'widget/lib/map/trip_label_fn',
helpId: 'widget/lib/map/label_fn',
condition: 'model.showLabel === true && model.useLabelFunction === true'
},
'showTooltip',
@ -1184,7 +1184,7 @@ export const tripAnimationSchema = {
{
key: 'tooltipFunction',
type: 'javascript',
helpId: 'widget/lib/map/trip_tooltip_fn',
helpId: 'widget/lib/map/tooltip_fn',
condition: 'model.showTooltip === true && model.useTooltipFunction === true'
},
'rotationAngle',
@ -1201,7 +1201,7 @@ export const tripAnimationSchema = {
{
key: 'markerImageFunction',
type: 'javascript',
helpId: 'widget/lib/map/trip_marker_image_fn',
helpId: 'widget/lib/map/marker_image_fn',
condition: 'model.useMarkerImageFunction === true'
},
{

4
ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.html

@ -16,9 +16,7 @@
-->
<div class="trip-animation-widget">
<div class="trip-animation-label-container" *ngIf="settings.showLabel">
{{label}}
</div>
<div class="trip-animation-label-container" *ngIf="settings.showLabel" [innerHTML]="label"></div>
<div class="trip-animation-container" fxLayout="column">
<div class="map" #map></div>
<div class="trip-animation-info-panel" fxLayout="row">

43
ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts

@ -30,7 +30,7 @@ import {
import { FormattedData, MapProviders, TripAnimationSettings } from '@home/components/widget/lib/maps/map-models';
import { addCondition, addGroupInfo, addToSchema, initSchema } from '@app/core/schema-utils';
import { mapPolygonSchema, pathSchema, pointSchema, tripAnimationSchema } from '@home/components/widget/lib/maps/schemes';
import { DomSanitizer } from '@angular/platform-browser';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { WidgetContext } from '@app/modules/home/models/widget-component.models';
import {
findAngle, getProviderSchema,
@ -70,13 +70,14 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
mapWidget: MapWidgetInterface;
historicalData: FormattedData[][];
normalizationStep: number;
interpolatedTimeData = [];
interpolatedTimeData: {[time: number]: FormattedData}[] = [];
formattedInterpolatedTimeData: FormattedData[][] = [];
widgetConfig: WidgetConfig;
settings: TripAnimationSettings;
mainTooltips = [];
visibleTooltip = false;
activeTrip: FormattedData;
label: string;
label: SafeHtml;
minTime: number;
maxTime: number;
anchors: number[] = [];
@ -117,6 +118,8 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
const subscription = this.ctx.defaultSubscription;
subscription.callbacks.onDataUpdated = () => {
this.historicalData = parseArray(this.ctx.data).filter(arr => arr.length);
this.interpolatedTimeData.length = 0;
this.formattedInterpolatedTimeData.length = 0;
if (this.historicalData.length) {
this.calculateIntervals();
this.timeUpdated(this.minTime);
@ -146,6 +149,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
timeUpdated(time: number) {
this.currentTime = time;
// get point for each datasource associated with time
const currentPosition = this.interpolatedTimeData
.map(dataSource => dataSource[time]);
for (let j = 0; j < this.interpolatedTimeData.length; j++) {
@ -171,20 +175,20 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
currentPosition[j] = this.calculateLastPoints(this.interpolatedTimeData[j], time);
}
}
this.calcLabel();
this.calcLabel(currentPosition);
this.calcMainTooltip(currentPosition);
if (this.mapWidget && this.mapWidget.map && this.mapWidget.map.map) {
const formattedInterpolatedTimeData = this.interpolatedTimeData.map(ds => _.values(ds));
this.mapWidget.map.updatePolylines(formattedInterpolatedTimeData, true);
this.mapWidget.map.updatePolylines(this.formattedInterpolatedTimeData, currentPosition, true);
if (this.settings.showPolygon) {
this.mapWidget.map.updatePolygons(this.interpolatedTimeData);
this.mapWidget.map.updatePolygons(currentPosition);
}
if (this.settings.showPoints) {
this.mapWidget.map.updatePoints(formattedInterpolatedTimeData.map(ds => _.union(ds)), this.calcTooltip);
this.mapWidget.map.updatePoints(this.formattedInterpolatedTimeData, this.calcTooltip);
}
this.mapWidget.map.updateMarkers(currentPosition, true, (trip) => {
this.activeTrip = trip;
this.timeUpdated(this.currentTime);
this.cd.markForCheck();
});
}
}
@ -215,41 +219,44 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
this.maxTime = dataSource[dataSource.length - 1]?.time || -Infinity;
this.interpolatedTimeData[index] = this.interpolateArray(dataSource);
});
this.formattedInterpolatedTimeData = this.interpolatedTimeData.map(ds => _.values(ds));
if (!this.activeTrip) {
this.activeTrip = this.interpolatedTimeData.map(dataSource => dataSource[this.minTime]).filter(ds => ds)[0];
}
if (this.useAnchors) {
const anchorDate = Object.entries(_.union(this.interpolatedTimeData)[0]);
this.anchors = anchorDate
.filter((data: [string, FormattedData]) => safeExecute(this.settings.pointAsAnchorFunction, [data[1], anchorDate, data[1].dsIndex]))
.filter((data: [string, FormattedData], tsIndex) => safeExecute(this.settings.pointAsAnchorFunction, [data[1],
this.formattedInterpolatedTimeData.map(ds => ds[tsIndex]), data[1].dsIndex]))
.map(data => parseInt(data[0], 10));
}
}
calcTooltip = (point: FormattedData): string => {
calcTooltip = (point: FormattedData, points: FormattedData[]): string => {
const data = point ? point : this.activeTrip;
const tooltipPattern: string = this.settings.useTooltipFunction ?
safeExecute(this.settings.tooltipFunction, [data, this.historicalData, point.dsIndex]) : this.settings.tooltipPattern;
safeExecute(this.settings.tooltipFunction,
[data, points, point.dsIndex]) : this.settings.tooltipPattern;
return parseWithTranslation.parseTemplate(tooltipPattern, data, true);
}
private calcMainTooltip(points: FormattedData[]): void {
const tooltips = [];
for (const point of points) {
tooltips.push(this.sanitizer.sanitize(SecurityContext.HTML, this.calcTooltip(point)));
tooltips.push(this.sanitizer.sanitize(SecurityContext.HTML, this.calcTooltip(point, points)));
}
this.mainTooltips = tooltips;
}
calcLabel() {
const data = this.activeTrip;
calcLabel(points: FormattedData[]) {
const data = points[this.activeTrip.dsIndex];
const labelText: string = this.settings.useLabelFunction ?
safeExecute(this.settings.labelFunction, [data, this.historicalData, data.dsIndex]) : this.settings.label;
this.label = (parseWithTranslation.parseTemplate(labelText, data, true));
safeExecute(this.settings.labelFunction, [data, points, data.dsIndex]) : this.settings.label;
this.label = this.sanitizer.bypassSecurityTrustHtml(parseWithTranslation.parseTemplate(labelText, data, true));
}
interpolateArray(originData: FormattedData[]) {
const result = {};
interpolateArray(originData: FormattedData[]): {[time: number]: FormattedData} {
const result: {[time: number]: FormattedData} = {};
const latKeyName = this.settings.latKeyName;
const lngKeyName = this.settings.lngKeyName;
for (const data of originData) {

6
ui-ngx/src/assets/help/en_US/widget/lib/map/map_fn_args.md

@ -1,10 +1,10 @@
<li><b>data:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a></code> - A <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a> object associated with marker.<br/>
<li><b>data:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a></code> - A <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a> object associated with marker or data point of the route.<br/>
Represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>and provides access to other entity attributes/timeseries declared in widget datasource configuration.
</li>
<li><b>dsData:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData[]</a></code> - All available widget data (entities) as array of <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a> objects<br/>
<li><b>dsData:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData[]</a></code> - All available data associated with markers or routes data points as array of <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a> objects<br/>
resolved from configured datasources. Each object represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>
and provides access to other entity attributes/timeseries declared in widget datasource configuration.
</li>
<li><b>dsIndex</b> <code>number</code> - index of the current marker data in <code>dsData</code> array.<br>
<li><b>dsIndex</b> <code>number</code> - index of the current marker data or route data point in <code>dsData</code> array.<br>
<strong>Note: </strong> The <code>data</code> argument is equivalent to <code>dsData[dsIndex]</code> expression.
</li>

2
ui-ngx/src/assets/help/en_US/widget/lib/map/trip_path_color_fn.md → ui-ngx/src/assets/help/en_US/widget/lib/map/path_color_fn.md

@ -10,7 +10,7 @@ A JavaScript function used to compute color of the trip path.
**Parameters:**
<ul>
{% include widget/lib/map/trip_fn_args %}
{% include widget/lib/map/map_fn_args %}
</ul>
**Returns:**

2
ui-ngx/src/assets/help/en_US/widget/lib/map/trip_path_point_color_fn.md → ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_color_fn.md

@ -10,7 +10,7 @@ A JavaScript function used to compute color of the trip path point.
**Parameters:**
<ul>
{% include widget/lib/map/trip_fn_args %}
{% include widget/lib/map/map_fn_args %}
</ul>
**Returns:**

4
ui-ngx/src/assets/help/en_US/widget/lib/map/tooltip_fn.md

@ -5,7 +5,7 @@
*function (data, dsData, dsIndex): string*
A JavaScript function used to compute text or HTML code to be displayed in the marker tooltip.
A JavaScript function used to compute text or HTML code to be displayed in the marker, point or polygon tooltip.
**Parameters:**
@ -15,7 +15,7 @@ A JavaScript function used to compute text or HTML code to be displayed in the m
**Returns:**
Should return string value presenting text or HTML for the marker tooltip.
Should return string value presenting text or HTML for the tooltip.
<div class="divider"></div>

11
ui-ngx/src/assets/help/en_US/widget/lib/map/trip_fn_args.md

@ -1,11 +0,0 @@
<li><b>data:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a></code> - A <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a> object associated with the point of the trip.<br/>
Represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>and provides access to other entity attributes/timeseries declared in widget datasource configuration.
</li>
<li><b>dsData:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData[][]</a></code> - two-dimensional array of <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a> objects presenting<br/>
array of trips (entities with timeseries data) resolved from configured datasources.<br/>
Each element of array is particular entity trip data presented as array of <b>FormattedData</b> object (trip point).<br/>
Each object represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>
and provides access to other entity attributes/timeseries declared in widget datasource configuration.
</li>
<li><b>dsIndex</b> <code>number</code> - index of the current trip data in <code>dsData</code> array.
</li>

40
ui-ngx/src/assets/help/en_US/widget/lib/map/trip_label_fn.md

@ -1,40 +0,0 @@
#### Trip animation widget label function
<div class="divider"></div>
<br/>
*function (data, dsData, dsIndex): string*
A JavaScript function used to compute text or HTML code of the marker label.
**Parameters:**
<ul>
{% include widget/lib/map/trip_fn_args %}
</ul>
**Returns:**
Should return string value presenting text or HTML of the marker label.
<div class="divider"></div>
##### Examples
* Display styled label with corresponding latest telemetry data for `energy meter` or `thermometer` device types:
```javascript
var deviceType = data['Type'];
if (typeof deviceType !== undefined) {
if (deviceType == "energy meter") {
return '<span style="color:orange;">${entityName}, ${energy:2} kWt</span>';
} else if (deviceType == "thermometer") {
return '<span style="color:blue;">${entityName}, ${temperature:2} °C</span>';
}
}
return data.entityName;
{:copy-code}
```
<br>
<br>

62
ui-ngx/src/assets/help/en_US/widget/lib/map/trip_marker_image_fn.md

@ -1,62 +0,0 @@
#### Marker image function
<div class="divider"></div>
<br/>
*function (data, images, dsData, dsIndex): {url: string, size: number}*
A JavaScript function used to compute marker image.
**Parameters:**
<ul>
{% include widget/lib/map/trip_fn_args %}
</ul>
**Returns:**
Should return marker image data having the following structure:
```typescript
{
url: string,
size: number
}
```
- *url* - marker image url;
- *size* - marker image size;
In case no data is returned, default marker image will be used.
<div class="divider"></div>
##### Examples
<ul>
<li>
Calculate image url depending on <code>temperature</code> telemetry value for <code>thermometer</code> device type.<br>
Let's assume 4 images are defined in <b>Marker images</b> section. Each image corresponds to particular temperature level:
</li>
</ul>
```javascript
var type = data['Type'];
if (type == 'thermometer') {
var res = {
url: images[0],
size: 40
}
var temperature = data['temperature'];
if (typeof temperature !== undefined) {
var percent = (temperature + 60)/120;
var index = Math.min(3, Math.floor(4 * percent));
res.url = images[index];
}
return res;
}
{:copy-code}
```
<br>
<br>

2
ui-ngx/src/assets/help/en_US/widget/lib/map/trip_point_as_anchor_fn.md

@ -10,7 +10,7 @@ A JavaScript function evaluating whether to use trip point as time anchor used i
**Parameters:**
<ul>
{% include widget/lib/map/trip_fn_args %}
{% include widget/lib/map/map_fn_args %}
</ul>
**Returns:**

40
ui-ngx/src/assets/help/en_US/widget/lib/map/trip_tooltip_fn.md

@ -1,40 +0,0 @@
#### Trip animation widget tooltip function
<div class="divider"></div>
<br/>
*function (data, dsData, dsIndex): string*
A JavaScript function used to compute text or HTML code to be displayed in the marker tooltip.
**Parameters:**
<ul>
{% include widget/lib/map/trip_fn_args %}
</ul>
**Returns:**
Should return string value presenting text or HTML for the marker tooltip.
<div class="divider"></div>
##### Examples
* Display details with corresponding telemetry data for `thermostat` device type:
```javascript
var deviceType = data['Type'];
if (typeof deviceType !== undefined) {
if (deviceType == "energy meter") {
return '<b>${entityName}</b><br/><b>Energy:</b> ${energy:2} kWt<br/>';
} else if (deviceType == "thermometer") {
return '<b>${entityName}</b><br/><b>Temperature:</b> ${temperature:2} °C<br/>';
}
}
return data.entityName;
{:copy-code}
```
<br>
<br>
Loading…
Cancel
Save