bugfixes (#2705)
This commit is contained in:
parent
c6cf5c43ad
commit
11db772ea2
@ -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 {
|
||||||
|
|||||||
@ -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({
|
||||||
@ -101,8 +101,8 @@ export class UtilsService {
|
|||||||
materialIcons: Array<string> = [];
|
materialIcons: Array<string> = [];
|
||||||
|
|
||||||
constructor(@Inject(WINDOW) private window: Window,
|
constructor(@Inject(WINDOW) private window: Window,
|
||||||
private zone: NgZone,
|
private zone: NgZone,
|
||||||
private translate: TranslateService) {
|
private translate: TranslateService) {
|
||||||
let frame: Element = null;
|
let frame: Element = null;
|
||||||
try {
|
try {
|
||||||
frame = window.frameElement;
|
frame = window.frameElement;
|
||||||
@ -302,10 +302,10 @@ export class UtilsService {
|
|||||||
.split('\n')
|
.split('\n')
|
||||||
.filter((codepoint) => codepoint && codepoint.length);
|
.filter((codepoint) => codepoint && codepoint.length);
|
||||||
codepointsArray.forEach((codepoint) => {
|
codepointsArray.forEach((codepoint) => {
|
||||||
const values = codepoint.split(' ');
|
const values = codepoint.split(' ');
|
||||||
if (values && values.length === 2) {
|
if (values && values.length === 2) {
|
||||||
this.materialIcons.push(values[0]);
|
this.materialIcons.push(values[0]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
materialIconsSubject.next(this.materialIcons);
|
materialIconsSubject.next(this.materialIcons);
|
||||||
});
|
});
|
||||||
@ -360,12 +360,12 @@ export class UtilsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public createAdditionalDataKey(dataKey: DataKey, datasource: Datasource, timeUnit: string,
|
public createAdditionalDataKey(dataKey: DataKey, datasource: Datasource, timeUnit: string,
|
||||||
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>) {
|
||||||
@ -456,7 +433,7 @@ export class UtilsService {
|
|||||||
params = urlQueryString + '&' + newParam;
|
params = urlQueryString + '&' + newParam;
|
||||||
}
|
}
|
||||||
} else if (newParam) {
|
} else if (newParam) {
|
||||||
params = '?' + newParam;
|
params = '?' + newParam;
|
||||||
}
|
}
|
||||||
this.window.history.replaceState({}, '', baseUrl + params);
|
this.window.history.replaceState({}, '', baseUrl + params);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 => {
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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',
|
||||||
|
|||||||
@ -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[] {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user