This commit is contained in:
ArtemHalushko 2020-05-04 11:40:54 +03:00 committed by GitHub
parent c6cf5c43ad
commit 11db772ea2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 112 additions and 73 deletions

View File

@ -17,7 +17,7 @@
import { AliasInfo, IAliasController, StateControllerHolder, StateEntityInfo } from '@core/api/widget-api.models'; import { AliasInfo, IAliasController, StateControllerHolder, StateEntityInfo } from '@core/api/widget-api.models';
import { forkJoin, Observable, of, ReplaySubject, Subject } from 'rxjs'; import { forkJoin, Observable, of, ReplaySubject, Subject } from 'rxjs';
import { DataKey, Datasource, DatasourceType } from '@app/shared/models/widget.models'; import { DataKey, Datasource, DatasourceType } from '@app/shared/models/widget.models';
import { deepClone, isEqual } from '@core/utils'; import { deepClone, isEqual, createLabelFromDatasource } from '@core/utils';
import { EntityService } from '@core/http/entity.service'; import { EntityService } from '@core/http/entity.service';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { EntityAliases } from '@shared/models/alias.models'; import { EntityAliases } from '@shared/models/alias.models';
@ -329,7 +329,7 @@ export class AliasController implements IAliasController {
if (!dataKey.pattern) { if (!dataKey.pattern) {
dataKey.pattern = deepClone(dataKey.label); dataKey.pattern = deepClone(dataKey.label);
} }
dataKey.label = this.utils.createLabelFromDatasource(datasource, dataKey.pattern); dataKey.label = createLabelFromDatasource(datasource, dataKey.pattern);
} }
getInstantAliasInfo(aliasId: string): AliasInfo { getInstantAliasInfo(aliasId: string): AliasInfo {

View File

@ -20,7 +20,7 @@
import { Inject, Injectable, NgZone } from '@angular/core'; import { Inject, Injectable, NgZone } from '@angular/core';
import { WINDOW } from '@core/services/window.service'; import { WINDOW } from '@core/services/window.service';
import { ExceptionData } from '@app/shared/models/error.models'; import { ExceptionData } from '@app/shared/models/error.models';
import { deepClone, deleteNullProperties, guid, isDefined, isDefinedAndNotNull, isUndefined } from '@core/utils'; import { deepClone, deleteNullProperties, guid, isDefined, isDefinedAndNotNull, isUndefined, createLabelFromDatasource } from '@core/utils';
import { WindowMessage } from '@shared/models/window-message.model'; import { WindowMessage } from '@shared/models/window-message.model';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { customTranslationsPrefix } from '@app/shared/models/constants'; import { customTranslationsPrefix } from '@app/shared/models/constants';
@ -36,7 +36,7 @@ import { Observable, of, ReplaySubject } from 'rxjs';
const varsRegex = /\$\{([^}]*)\}/g; const varsRegex = /\$\{([^}]*)\}/g;
const predefinedFunctions: {[func: string]: string} = { const predefinedFunctions: { [func: string]: string } = {
Sin: 'return Math.round(1000*Math.sin(time/5000));', Sin: 'return Math.round(1000*Math.sin(time/5000));',
Cos: 'return Math.round(1000*Math.cos(time/5000));', Cos: 'return Math.round(1000*Math.cos(time/5000));',
Random: 'var value = prevValue + Math.random() * 100 - 50;\n' + Random: 'var value = prevValue + Math.random() * 100 - 50;\n' +
@ -63,12 +63,12 @@ const defaultAlarmFields: Array<string> = [
alarmFields.status.keyName alarmFields.status.keyName
]; ];
const commonMaterialIcons: Array<string> = [ 'more_horiz', 'more_vert', 'open_in_new', const commonMaterialIcons: Array<string> = ['more_horiz', 'more_vert', 'open_in_new',
'visibility', 'play_arrow', 'arrow_back', 'arrow_downward', 'visibility', 'play_arrow', 'arrow_back', 'arrow_downward',
'arrow_forward', 'arrow_upwards', 'close', 'refresh', 'menu', 'show_chart', 'multiline_chart', 'pie_chart', 'insert_chart', 'people', 'arrow_forward', 'arrow_upwards', 'close', 'refresh', 'menu', 'show_chart', 'multiline_chart', 'pie_chart', 'insert_chart', 'people',
'person', 'domain', 'devices_other', 'now_widgets', 'dashboards', 'map', 'pin_drop', 'my_location', 'extension', 'search', 'person', 'domain', 'devices_other', 'now_widgets', 'dashboards', 'map', 'pin_drop', 'my_location', 'extension', 'search',
'settings', 'notifications', 'notifications_active', 'info', 'info_outline', 'warning', 'list', 'file_download', 'import_export', 'settings', 'notifications', 'notifications_active', 'info', 'info_outline', 'warning', 'list', 'file_download', 'import_export',
'share', 'add', 'edit', 'done' ]; 'share', 'add', 'edit', 'done'];
// @dynamic // @dynamic
@Injectable({ @Injectable({
@ -363,9 +363,9 @@ export class UtilsService {
datasources: Datasource[], additionalKeysNumber: number): DataKey { datasources: Datasource[], additionalKeysNumber: number): DataKey {
const additionalDataKey = deepClone(dataKey); const additionalDataKey = deepClone(dataKey);
if (dataKey.settings.comparisonSettings.comparisonValuesLabel) { if (dataKey.settings.comparisonSettings.comparisonValuesLabel) {
additionalDataKey.label = this.createLabelFromDatasource(datasource, dataKey.settings.comparisonSettings.comparisonValuesLabel); additionalDataKey.label = createLabelFromDatasource(datasource, dataKey.settings.comparisonSettings.comparisonValuesLabel);
} else { } else {
additionalDataKey.label = dataKey.label + ' ' + this.translate.instant('legend.comparison-time-ago.'+timeUnit); additionalDataKey.label = dataKey.label + ' ' + this.translate.instant('legend.comparison-time-ago.' + timeUnit);
} }
additionalDataKey.pattern = additionalDataKey.label; additionalDataKey.pattern = additionalDataKey.label;
if (dataKey.settings.comparisonSettings.color) { if (dataKey.settings.comparisonSettings.color) {
@ -380,30 +380,7 @@ export class UtilsService {
} }
public createLabelFromDatasource(datasource: Datasource, pattern: string) { public createLabelFromDatasource(datasource: Datasource, pattern: string) {
let label = pattern; return createLabelFromDatasource(datasource, pattern);
if (!datasource) {
return label;
}
let match = varsRegex.exec(pattern);
while (match !== null) {
const variable = match[0];
const variableName = match[1];
if (variableName === 'dsName') {
label = label.split(variable).join(datasource.name);
} else if (variableName === 'entityName') {
label = label.split(variable).join(datasource.entityName);
} else if (variableName === 'deviceName') {
label = label.split(variable).join(datasource.entityName);
} else if (variableName === 'entityLabel') {
label = label.split(variable).join(datasource.entityLabel || datasource.entityName);
} else if (variableName === 'aliasName') {
label = label.split(variable).join(datasource.aliasName);
} else if (variableName === 'entityDescription') {
label = label.split(variable).join(datasource.entityDescription);
}
match = varsRegex.exec(pattern);
}
return label;
} }
public generateColors(datasources: Array<Datasource>) { public generateColors(datasources: Array<Datasource>) {

View File

@ -18,6 +18,7 @@ import _ from 'lodash';
import { Observable, Subject, fromEvent, of } from 'rxjs'; import { Observable, Subject, fromEvent, of } from 'rxjs';
import { finalize, share, map } from 'rxjs/operators'; import { finalize, share, map } from 'rxjs/operators';
import base64js from 'base64-js'; import base64js from 'base64-js';
import { Datasource } from '@app/shared/models/widget.models';
export function onParentScrollOrWindowResize(el: Node): Observable<Event> { export function onParentScrollOrWindowResize(el: Node): Observable<Event> {
const scrollSubject = new Subject<Event>(); const scrollSubject = new Subject<Event>();
@ -435,6 +436,34 @@ export function imageLoader(imageUrl: string): Observable<HTMLImageElement> {
return imageLoad$; return imageLoad$;
} }
export function createLabelFromDatasource(datasource: Datasource, pattern: string) {
const varsRegex = /\$\{([^}]*)\}/g;
let label = pattern;
if (!datasource) {
return label;
}
let match = varsRegex.exec(pattern);
while (match !== null) {
const variable = match[0];
const variableName = match[1];
if (variableName === 'dsName') {
label = label.split(variable).join(datasource.name);
} else if (variableName === 'entityName') {
label = label.split(variable).join(datasource.entityName);
} else if (variableName === 'deviceName') {
label = label.split(variable).join(datasource.entityName);
} else if (variableName === 'entityLabel') {
label = label.split(variable).join(datasource.entityLabel || datasource.entityName);
} else if (variableName === 'aliasName') {
label = label.split(variable).join(datasource.aliasName);
} else if (variableName === 'entityDescription') {
label = label.split(variable).join(datasource.entityDescription);
}
match = varsRegex.exec(pattern);
}
return label;
}
const imageAspectMap = {}; const imageAspectMap = {};
export function aspectCache(imageUrl: string): Observable<number> { export function aspectCache(imageUrl: string): Observable<number> {
@ -452,7 +481,6 @@ export function aspectCache(imageUrl: string): Observable<number> {
} }
} }
export function parseArray(input: any[]): any[] { export function parseArray(input: any[]): any[] {
return _(input).groupBy(el => el?.datasource?.entityName) return _(input).groupBy(el => el?.datasource?.entityName)
.values().value().map((entityArray, dsIndex) => .values().value().map((entityArray, dsIndex) =>
@ -523,15 +551,18 @@ export function parseFunction(source: any, params: string[] = ['def']): Function
return res; return res;
} }
export function parseTemplate(template: string, data: object, translateFn?: (key: string) => string) { export function parseTemplate(template: string, data: { $datasource?: Datasource, [key: string]: any },
translateFn?: (key: string) => string) {
let res = ''; let res = '';
try { try {
if (template.match(/<link-act/g)) { if (template.match(/<link-act/g)) {
template = template.replace(/<link-act/g, '<a').replace(/link-act>/g, 'a>').replace(/name=(\'|")(.*?)(\'|")/g, `class='tb-custom-action' id='$2'`); template = template.replace(/<link-act/g, '<a').replace(/link-act>/g, 'a>')
.replace(/name=(\'|")(.*?)(\'|")/g, `class='tb-custom-action' id='$2'`);
} }
if (translateFn) { if (translateFn) {
template = translateFn(template); template = translateFn(template);
} }
template = createLabelFromDatasource(data.$datasource, template);
const formatted = template.match(/\$\{([^}]*)\:\d*\}/g); const formatted = template.match(/\$\{([^}]*)\:\d*\}/g);
if (formatted) if (formatted)
formatted.forEach(value => { formatted.forEach(value => {

View File

@ -33,7 +33,7 @@ import { Datasource, WidgetActionDescriptor, WidgetConfig } from '@shared/models
import { IWidgetSubscription } from '@core/api/widget-api.models'; import { IWidgetSubscription } from '@core/api/widget-api.models';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { deepClone, isDefined, isNumber } from '@core/utils'; import { deepClone, isDefined, isNumber, createLabelFromDatasource } from '@core/utils';
import cssjs from '@core/css/css'; import cssjs from '@core/css/css';
import { PageLink } from '@shared/models/page/page-link'; import { PageLink } from '@shared/models/page/page-link';
import { Direction, SortOrder, sortOrderFromString } from '@shared/models/page/sort-order'; import { Direction, SortOrder, sortOrderFromString } from '@shared/models/page/sort-order';
@ -282,7 +282,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
alarmsTitle = this.translate.instant('alarm.alarms'); alarmsTitle = this.translate.instant('alarm.alarms');
} }
this.ctx.widgetTitle = this.utils.createLabelFromDatasource(this.alarmSource, alarmsTitle); this.ctx.widgetTitle = createLabelFromDatasource(this.alarmSource, alarmsTitle);
this.enableSelection = isDefined(this.settings.enableSelection) ? this.settings.enableSelection : true; this.enableSelection = isDefined(this.settings.enableSelection) ? this.settings.enableSelection : true;
if (!this.allowAcknowledgment && !this.allowClear) { if (!this.allowAcknowledgment && !this.allowClear) {

View File

@ -39,7 +39,7 @@ import {
import { IWidgetSubscription } from '@core/api/widget-api.models'; import { IWidgetSubscription } from '@core/api/widget-api.models';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { deepClone, isDefined, isNumber } from '@core/utils'; import { deepClone, isDefined, isNumber, createLabelFromDatasource } from '@core/utils';
import cssjs from '@core/css/css'; import cssjs from '@core/css/css';
import { PageLink } from '@shared/models/page/page-link'; import { PageLink } from '@shared/models/page/page-link';
import { Direction, SortOrder, sortOrderFromString } from '@shared/models/page/sort-order'; import { Direction, SortOrder, sortOrderFromString } from '@shared/models/page/sort-order';
@ -210,7 +210,7 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni
} }
const datasource = this.subscription.datasources[0]; const datasource = this.subscription.datasources[0];
this.ctx.widgetTitle = this.utils.createLabelFromDatasource(datasource, entitiesTitle); this.ctx.widgetTitle = createLabelFromDatasource(datasource, entitiesTitle);
this.searchAction.show = isDefined(this.settings.enableSearch) ? this.settings.enableSearch : true; this.searchAction.show = isDefined(this.settings.enableSearch) ? this.settings.enableSearch : true;
this.displayPagination = isDefined(this.settings.displayPagination) ? this.settings.displayPagination : true; this.displayPagination = isDefined(this.settings.displayPagination) ? this.settings.displayPagination : true;

View File

@ -26,6 +26,7 @@ import { filter } from 'rxjs/operators';
import { Polyline } from './polyline'; import { Polyline } from './polyline';
import { Polygon } from './polygon'; import { Polygon } from './polygon';
import { DatasourceData } from '@app/shared/models/widget.models'; import { DatasourceData } from '@app/shared/models/widget.models';
import { safeExecute } from '@app/core/utils';
export default abstract class LeafletMap { export default abstract class LeafletMap {
@ -87,12 +88,14 @@ export default abstract class LeafletMap {
if (this.options.draggableMarker) { if (this.options.draggableMarker) {
let mousePositionOnMap: L.LatLng; let mousePositionOnMap: L.LatLng;
let addMarker: L.Control; let addMarker: L.Control;
this.map.on('mouseup', (e: L.LeafletMouseEvent) => { this.map.on('mousemove', (e: L.LeafletMouseEvent) => {
mousePositionOnMap = e.latlng; mousePositionOnMap = e.latlng;
}); });
const dragListener = (e: L.DragEndEvent) => { const dragListener = (e: L.DragEndEvent) => {
if (e.type === 'dragend' && mousePositionOnMap) { if (e.type === 'dragend' && mousePositionOnMap) {
const newMarker = L.marker(mousePositionOnMap).addTo(this.map); const icon = new L.Icon.Default();
icon.options.shadowSize = [0, 0];
const newMarker = L.marker(mousePositionOnMap, { icon }).addTo(this.map);
const datasourcesList = document.createElement('div'); const datasourcesList = document.createElement('div');
const customLatLng = this.convertToCustomFormat(mousePositionOnMap); const customLatLng = this.convertToCustomFormat(mousePositionOnMap);
this.datasources.forEach(ds => { this.datasources.forEach(ds => {
@ -195,15 +198,18 @@ export default abstract class LeafletMap {
fitBounds(bounds: LatLngBounds, useDefaultZoom = false, padding?: LatLngTuple) { fitBounds(bounds: LatLngBounds, useDefaultZoom = false, padding?: LatLngTuple) {
if (bounds.isValid()) { if (bounds.isValid()) {
if ((!this.options.fitMapBounds || useDefaultZoom) && this.options.defaultZoomLevel) { if ((!this.options.fitMapBounds || this.options.useDefaultCenterPosition) && this.options.defaultZoomLevel) {
this.map.setZoom(this.options.defaultZoomLevel, { animate: false }); this.map.setZoom(this.options.defaultZoomLevel, { animate: false });
this.map.panTo(bounds.getCenter(), { animate: false }); this.map.panTo(this.options.defaultCenterPosition, { animate: false });
} else { } else {
this.map.once('zoomend', () => { this.map.once('zoomend', () => {
if (!this.options.defaultZoomLevel && this.map.getZoom() > this.options.minZoomLevel) { if (!this.options.defaultZoomLevel && this.map.getZoom() > this.options.minZoomLevel) {
this.map.setZoom(this.options.minZoomLevel, { animate: false }); this.map.setZoom(this.options.minZoomLevel, { animate: false });
} }
}); });
if (this.options.useDefaultCenterPosition) {
bounds = bounds.extend(this.options.defaultCenterPosition);
}
this.map.fitBounds(bounds, { padding: padding || [50, 50], animate: false }); this.map.fitBounds(bounds, { padding: padding || [50, 50], animate: false });
} }
this.bounds = bounds; this.bounds = bounds;
@ -231,8 +237,16 @@ export default abstract class LeafletMap {
updateMarkers(markersData) { updateMarkers(markersData) {
markersData.filter(mdata => !!this.convertPosition(mdata)).forEach(data => { markersData.filter(mdata => !!this.convertPosition(mdata)).forEach(data => {
if (data.rotationAngle || data.rotationAngle === 0) { if (data.rotationAngle || data.rotationAngle === 0) {
const currentImage = this.options.useMarkerImageFunction ?
safeExecute(this.options.markerImageFunction,
[data, this.options.markerImages, markersData, data.dsIndex]) : this.options.currentImage;
const style = currentImage ? 'background-image: url(' + currentImage.url + ');' : '';
this.options.icon = L.divIcon({ this.options.icon = L.divIcon({
html: `<div class="arrow" style="transform: translate(-10px, -10px) rotate(${data.rotationAngle}deg);"><div>` html: `<div class="arrow"
style="transform: translate(-10px, -10px);
${style}
rotate(${data.rotationAngle}deg);
"><div>`
}) })
} }
else { else {
@ -335,31 +349,28 @@ export default abstract class LeafletMap {
data.data = JSON.parse(data.data[0][1]) as LatLngTuple[]; data.data = JSON.parse(data.data[0][1]) as LatLngTuple[];
} }
if (this.polygons.get(data.datasource.entityName)) { if (this.polygons.get(data.datasource.entityName)) {
this.updatePolygon(data.datasource.entityName, data.data, polyData, this.options); this.updatePolygon(data, polyData, this.options);
} }
else { else {
this.createPolygon(data.datasource.entityName, data.data, polyData, this.options); this.createPolygon(data, polyData, this.options);
} }
} }
}); });
} }
createPolygon(key: string, data: LatLngTuple[], dataSources: DatasourceData[], settings: PolygonSettings) { createPolygon(polyData: DatasourceData, dataSources: DatasourceData[], settings: PolygonSettings) {
this.ready$.subscribe(() => { this.ready$.subscribe(() => {
const polygon = new Polygon(this.map, data, dataSources, settings); const polygon = new Polygon(this.map, polyData, dataSources, settings);
const bounds = this.bounds.extend(polygon.leafletPoly.getBounds()); const bounds = this.bounds.extend(polygon.leafletPoly.getBounds());
if (bounds.isValid()) { this.fitBounds(bounds);
this.map.fitBounds(bounds); this.polygons.set(polyData.datasource.entityName, polygon);
this.bounds = bounds;
}
this.polygons.set(key, polygon);
}); });
} }
updatePolygon(key: string, data: LatLngTuple[], dataSources: DatasourceData[], settings: PolygonSettings) { updatePolygon(polyData: DatasourceData, dataSources: DatasourceData[], settings: PolygonSettings) {
this.ready$.subscribe(() => { this.ready$.subscribe(() => {
const poly = this.polygons.get(key); const poly = this.polygons.get(polyData.datasource.entityName);
poly.updatePolygon(data, dataSources, settings); poly.updatePolygon(polyData.data, dataSources, settings);
this.fitBounds(poly.leafletPoly.getBounds()); this.fitBounds(poly.leafletPoly.getBounds());
}); });
} }

View File

@ -111,9 +111,13 @@ export type PolygonSettings = {
polygonStrokeWeight: number; polygonStrokeWeight: number;
polygonStrokeColor: string; polygonStrokeColor: string;
polygonColor: string; polygonColor: string;
showPolygonTooltip: boolean;
autocloseTooltip: boolean; autocloseTooltip: boolean;
tooltipFunction: GenericFunction;
showTooltipAction: string; showTooltipAction: string;
tooltipAction: object; tooltipAction: object;
tooltipPattern: string;
useTooltipFunction: boolean;
polygonClick: { [name: string]: actionsHandler }; polygonClick: { [name: string]: actionsHandler };
polygonColorFunction?: GenericFunction; polygonColorFunction?: GenericFunction;
} }

View File

@ -16,8 +16,9 @@
import L, { LatLngExpression, LatLngTuple } from 'leaflet'; import L, { LatLngExpression, LatLngTuple } from 'leaflet';
import { createTooltip } from './maps-utils'; import { createTooltip } from './maps-utils';
import { PolygonSettings } from './map-models'; import { PolygonSettings, FormattedData } from './map-models';
import { DatasourceData } from '@app/shared/models/widget.models'; import { DatasourceData } from '@app/shared/models/widget.models';
import { safeExecute, parseWithTranslation } from '@app/core/utils';
export class Polygon { export class Polygon {
@ -26,8 +27,8 @@ export class Polygon {
data; data;
dataSources; dataSources;
constructor(public map, coordinates, dataSources, settings: PolygonSettings, onClickListener?) { constructor(public map, polyData: DatasourceData, dataSources, private settings: PolygonSettings, onClickListener?) {
this.leafletPoly = L.polygon(coordinates, { this.leafletPoly = L.polygon(polyData.data, {
fill: true, fill: true,
fillColor: settings.polygonColor, fillColor: settings.polygonColor,
color: settings.polygonStrokeColor, color: settings.polygonStrokeColor,
@ -35,19 +36,29 @@ export class Polygon {
fillOpacity: settings.polygonOpacity, fillOpacity: settings.polygonOpacity,
opacity: settings.polygonStrokeOpacity opacity: settings.polygonStrokeOpacity
}).addTo(this.map); }).addTo(this.map);
this.dataSources = dataSources;
if (settings.showTooltip) { this.data = polyData;
if (settings.showPolygonTooltip) {
this.tooltip = createTooltip(this.leafletPoly, settings); this.tooltip = createTooltip(this.leafletPoly, settings);
this.updateTooltip(polyData);
} }
if (onClickListener) { if (onClickListener) {
this.leafletPoly.on('click', onClickListener); this.leafletPoly.on('click', onClickListener);
} }
} }
updateTooltip(data: DatasourceData) {
const pattern = this.settings.useTooltipFunction ?
safeExecute(this.settings.tooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) : this.settings.tooltipPattern;
this.tooltip.setContent(parseWithTranslation.parseTemplate(pattern, data, true));
}
updatePolygon(data: LatLngTuple[], dataSources: DatasourceData[], settings: PolygonSettings) { updatePolygon(data: LatLngTuple[], dataSources: DatasourceData[], settings: PolygonSettings) {
this.data = data; this.data = data;
this.dataSources = dataSources; this.dataSources = dataSources;
this.leafletPoly.setLatLngs(data); this.leafletPoly.setLatLngs(data);
if (settings.showPolygonTooltip)
this.updateTooltip(this.data);
this.updatePolygonColor(settings); this.updatePolygonColor(settings);
} }

View File

@ -477,6 +477,11 @@ export const mapPolygonSchema =
type: 'number', type: 'number',
default: 1 default: 1
}, },
showPolygonTooltip: {
title: 'Show polygon tooltip',
type: 'boolean',
default: false
},
usePolygonColorFunction: { usePolygonColorFunction: {
title: 'Use polygon color function', title: 'Use polygon color function',
type: 'boolean', type: 'boolean',
@ -501,7 +506,7 @@ export const mapPolygonSchema =
key: 'polygonStrokeColor', key: 'polygonStrokeColor',
type: 'color' type: 'color'
}, },
'polygonStrokeOpacity', 'polygonStrokeWeight', 'usePolygonColorFunction', 'polygonStrokeOpacity', 'polygonStrokeWeight', 'usePolygonColorFunction', 'showPolygonTooltip',
{ {
key: 'polygonColorFunction', key: 'polygonColorFunction',
type: 'javascript' type: 'javascript'
@ -1137,7 +1142,7 @@ export const tripAnimationSchema = {
rotationAngle: { rotationAngle: {
title: 'Set additional rotation angle for marker (deg)', title: 'Set additional rotation angle for marker (deg)',
type: 'number', type: 'number',
default: 180 default: 0
}, },
useMarkerImageFunction: { useMarkerImageFunction: {
title: 'Use marker image function', title: 'Use marker image function',

View File

@ -24,7 +24,7 @@ import { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { DataKey, Datasource, DatasourceData, DatasourceType, WidgetConfig } from '@shared/models/widget.models'; import { DataKey, Datasource, DatasourceData, DatasourceType, WidgetConfig } from '@shared/models/widget.models';
import { IWidgetSubscription } from '@core/api/widget-api.models'; import { IWidgetSubscription } from '@core/api/widget-api.models';
import { isDefined, isEqual, isUndefined } from '@core/utils'; import { isDefined, isEqual, isUndefined, createLabelFromDatasource } from '@core/utils';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import * as _moment from 'moment'; import * as _moment from 'moment';
import { FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms';
@ -331,7 +331,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
} }
public getGroupTitle(datasource: Datasource): string { public getGroupTitle(datasource: Datasource): string {
return this.utils.createLabelFromDatasource(datasource, this.settings.groupTitle); return createLabelFromDatasource(datasource, this.settings.groupTitle);
} }
public visibleKeys(source: MultipleInputWidgetSource): MultipleInputWidgetDataKey[] { public visibleKeys(source: MultipleInputWidgetSource): MultipleInputWidgetDataKey[] {