Commit 11db772ea2d753f178faa14e6eee0e2ac830b424
Committed by
GitHub
1 parent
c6cf5c43
bugfixes (#2705)
Showing
10 changed files
with
112 additions
and
73 deletions
... | ... | @@ -17,7 +17,7 @@ |
17 | 17 | import { AliasInfo, IAliasController, StateControllerHolder, StateEntityInfo } from '@core/api/widget-api.models'; |
18 | 18 | import { forkJoin, Observable, of, ReplaySubject, Subject } from 'rxjs'; |
19 | 19 | import { DataKey, Datasource, DatasourceType } from '@app/shared/models/widget.models'; |
20 | -import { deepClone, isEqual } from '@core/utils'; | |
20 | +import { deepClone, isEqual, createLabelFromDatasource } from '@core/utils'; | |
21 | 21 | import { EntityService } from '@core/http/entity.service'; |
22 | 22 | import { UtilsService } from '@core/services/utils.service'; |
23 | 23 | import { EntityAliases } from '@shared/models/alias.models'; |
... | ... | @@ -329,7 +329,7 @@ export class AliasController implements IAliasController { |
329 | 329 | if (!dataKey.pattern) { |
330 | 330 | dataKey.pattern = deepClone(dataKey.label); |
331 | 331 | } |
332 | - dataKey.label = this.utils.createLabelFromDatasource(datasource, dataKey.pattern); | |
332 | + dataKey.label = createLabelFromDatasource(datasource, dataKey.pattern); | |
333 | 333 | } |
334 | 334 | |
335 | 335 | getInstantAliasInfo(aliasId: string): AliasInfo { | ... | ... |
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | import { Inject, Injectable, NgZone } from '@angular/core'; |
21 | 21 | import { WINDOW } from '@core/services/window.service'; |
22 | 22 | import { ExceptionData } from '@app/shared/models/error.models'; |
23 | -import { deepClone, deleteNullProperties, guid, isDefined, isDefinedAndNotNull, isUndefined } from '@core/utils'; | |
23 | +import { deepClone, deleteNullProperties, guid, isDefined, isDefinedAndNotNull, isUndefined, createLabelFromDatasource } from '@core/utils'; | |
24 | 24 | import { WindowMessage } from '@shared/models/window-message.model'; |
25 | 25 | import { TranslateService } from '@ngx-translate/core'; |
26 | 26 | import { customTranslationsPrefix } from '@app/shared/models/constants'; |
... | ... | @@ -36,7 +36,7 @@ import { Observable, of, ReplaySubject } from 'rxjs'; |
36 | 36 | |
37 | 37 | const varsRegex = /\$\{([^}]*)\}/g; |
38 | 38 | |
39 | -const predefinedFunctions: {[func: string]: string} = { | |
39 | +const predefinedFunctions: { [func: string]: string } = { | |
40 | 40 | Sin: 'return Math.round(1000*Math.sin(time/5000));', |
41 | 41 | Cos: 'return Math.round(1000*Math.cos(time/5000));', |
42 | 42 | Random: 'var value = prevValue + Math.random() * 100 - 50;\n' + |
... | ... | @@ -63,12 +63,12 @@ const defaultAlarmFields: Array<string> = [ |
63 | 63 | alarmFields.status.keyName |
64 | 64 | ]; |
65 | 65 | |
66 | -const commonMaterialIcons: Array<string> = [ 'more_horiz', 'more_vert', 'open_in_new', | |
66 | +const commonMaterialIcons: Array<string> = ['more_horiz', 'more_vert', 'open_in_new', | |
67 | 67 | 'visibility', 'play_arrow', 'arrow_back', 'arrow_downward', |
68 | 68 | 'arrow_forward', 'arrow_upwards', 'close', 'refresh', 'menu', 'show_chart', 'multiline_chart', 'pie_chart', 'insert_chart', 'people', |
69 | 69 | 'person', 'domain', 'devices_other', 'now_widgets', 'dashboards', 'map', 'pin_drop', 'my_location', 'extension', 'search', |
70 | 70 | 'settings', 'notifications', 'notifications_active', 'info', 'info_outline', 'warning', 'list', 'file_download', 'import_export', |
71 | - 'share', 'add', 'edit', 'done' ]; | |
71 | + 'share', 'add', 'edit', 'done']; | |
72 | 72 | |
73 | 73 | // @dynamic |
74 | 74 | @Injectable({ |
... | ... | @@ -101,8 +101,8 @@ export class UtilsService { |
101 | 101 | materialIcons: Array<string> = []; |
102 | 102 | |
103 | 103 | constructor(@Inject(WINDOW) private window: Window, |
104 | - private zone: NgZone, | |
105 | - private translate: TranslateService) { | |
104 | + private zone: NgZone, | |
105 | + private translate: TranslateService) { | |
106 | 106 | let frame: Element = null; |
107 | 107 | try { |
108 | 108 | frame = window.frameElement; |
... | ... | @@ -302,10 +302,10 @@ export class UtilsService { |
302 | 302 | .split('\n') |
303 | 303 | .filter((codepoint) => codepoint && codepoint.length); |
304 | 304 | codepointsArray.forEach((codepoint) => { |
305 | - const values = codepoint.split(' '); | |
306 | - if (values && values.length === 2) { | |
307 | - this.materialIcons.push(values[0]); | |
308 | - } | |
305 | + const values = codepoint.split(' '); | |
306 | + if (values && values.length === 2) { | |
307 | + this.materialIcons.push(values[0]); | |
308 | + } | |
309 | 309 | }); |
310 | 310 | materialIconsSubject.next(this.materialIcons); |
311 | 311 | }); |
... | ... | @@ -360,12 +360,12 @@ export class UtilsService { |
360 | 360 | } |
361 | 361 | |
362 | 362 | public createAdditionalDataKey(dataKey: DataKey, datasource: Datasource, timeUnit: string, |
363 | - datasources: Datasource[], additionalKeysNumber: number): DataKey { | |
363 | + datasources: Datasource[], additionalKeysNumber: number): DataKey { | |
364 | 364 | const additionalDataKey = deepClone(dataKey); |
365 | 365 | if (dataKey.settings.comparisonSettings.comparisonValuesLabel) { |
366 | - additionalDataKey.label = this.createLabelFromDatasource(datasource, dataKey.settings.comparisonSettings.comparisonValuesLabel); | |
366 | + additionalDataKey.label = createLabelFromDatasource(datasource, dataKey.settings.comparisonSettings.comparisonValuesLabel); | |
367 | 367 | } else { |
368 | - additionalDataKey.label = dataKey.label + ' ' + this.translate.instant('legend.comparison-time-ago.'+timeUnit); | |
368 | + additionalDataKey.label = dataKey.label + ' ' + this.translate.instant('legend.comparison-time-ago.' + timeUnit); | |
369 | 369 | } |
370 | 370 | additionalDataKey.pattern = additionalDataKey.label; |
371 | 371 | if (dataKey.settings.comparisonSettings.color) { |
... | ... | @@ -380,30 +380,7 @@ export class UtilsService { |
380 | 380 | } |
381 | 381 | |
382 | 382 | public createLabelFromDatasource(datasource: Datasource, pattern: string) { |
383 | - let label = pattern; | |
384 | - if (!datasource) { | |
385 | - return label; | |
386 | - } | |
387 | - let match = varsRegex.exec(pattern); | |
388 | - while (match !== null) { | |
389 | - const variable = match[0]; | |
390 | - const variableName = match[1]; | |
391 | - if (variableName === 'dsName') { | |
392 | - label = label.split(variable).join(datasource.name); | |
393 | - } else if (variableName === 'entityName') { | |
394 | - label = label.split(variable).join(datasource.entityName); | |
395 | - } else if (variableName === 'deviceName') { | |
396 | - label = label.split(variable).join(datasource.entityName); | |
397 | - } else if (variableName === 'entityLabel') { | |
398 | - label = label.split(variable).join(datasource.entityLabel || datasource.entityName); | |
399 | - } else if (variableName === 'aliasName') { | |
400 | - label = label.split(variable).join(datasource.aliasName); | |
401 | - } else if (variableName === 'entityDescription') { | |
402 | - label = label.split(variable).join(datasource.entityDescription); | |
403 | - } | |
404 | - match = varsRegex.exec(pattern); | |
405 | - } | |
406 | - return label; | |
383 | + return createLabelFromDatasource(datasource, pattern); | |
407 | 384 | } |
408 | 385 | |
409 | 386 | public generateColors(datasources: Array<Datasource>) { |
... | ... | @@ -456,7 +433,7 @@ export class UtilsService { |
456 | 433 | params = urlQueryString + '&' + newParam; |
457 | 434 | } |
458 | 435 | } else if (newParam) { |
459 | - params = '?' + newParam; | |
436 | + params = '?' + newParam; | |
460 | 437 | } |
461 | 438 | this.window.history.replaceState({}, '', baseUrl + params); |
462 | 439 | } | ... | ... |
... | ... | @@ -18,6 +18,7 @@ import _ from 'lodash'; |
18 | 18 | import { Observable, Subject, fromEvent, of } from 'rxjs'; |
19 | 19 | import { finalize, share, map } from 'rxjs/operators'; |
20 | 20 | import base64js from 'base64-js'; |
21 | +import { Datasource } from '@app/shared/models/widget.models'; | |
21 | 22 | |
22 | 23 | export function onParentScrollOrWindowResize(el: Node): Observable<Event> { |
23 | 24 | const scrollSubject = new Subject<Event>(); |
... | ... | @@ -435,6 +436,34 @@ export function imageLoader(imageUrl: string): Observable<HTMLImageElement> { |
435 | 436 | return imageLoad$; |
436 | 437 | } |
437 | 438 | |
439 | +export function createLabelFromDatasource(datasource: Datasource, pattern: string) { | |
440 | + const varsRegex = /\$\{([^}]*)\}/g; | |
441 | + let label = pattern; | |
442 | + if (!datasource) { | |
443 | + return label; | |
444 | + } | |
445 | + let match = varsRegex.exec(pattern); | |
446 | + while (match !== null) { | |
447 | + const variable = match[0]; | |
448 | + const variableName = match[1]; | |
449 | + if (variableName === 'dsName') { | |
450 | + label = label.split(variable).join(datasource.name); | |
451 | + } else if (variableName === 'entityName') { | |
452 | + label = label.split(variable).join(datasource.entityName); | |
453 | + } else if (variableName === 'deviceName') { | |
454 | + label = label.split(variable).join(datasource.entityName); | |
455 | + } else if (variableName === 'entityLabel') { | |
456 | + label = label.split(variable).join(datasource.entityLabel || datasource.entityName); | |
457 | + } else if (variableName === 'aliasName') { | |
458 | + label = label.split(variable).join(datasource.aliasName); | |
459 | + } else if (variableName === 'entityDescription') { | |
460 | + label = label.split(variable).join(datasource.entityDescription); | |
461 | + } | |
462 | + match = varsRegex.exec(pattern); | |
463 | + } | |
464 | + return label; | |
465 | +} | |
466 | + | |
438 | 467 | const imageAspectMap = {}; |
439 | 468 | |
440 | 469 | export function aspectCache(imageUrl: string): Observable<number> { |
... | ... | @@ -452,7 +481,6 @@ export function aspectCache(imageUrl: string): Observable<number> { |
452 | 481 | } |
453 | 482 | } |
454 | 483 | |
455 | - | |
456 | 484 | export function parseArray(input: any[]): any[] { |
457 | 485 | return _(input).groupBy(el => el?.datasource?.entityName) |
458 | 486 | .values().value().map((entityArray, dsIndex) => |
... | ... | @@ -523,15 +551,18 @@ export function parseFunction(source: any, params: string[] = ['def']): Function |
523 | 551 | return res; |
524 | 552 | } |
525 | 553 | |
526 | -export function parseTemplate(template: string, data: object, translateFn?: (key: string) => string) { | |
554 | +export function parseTemplate(template: string, data: { $datasource?: Datasource, [key: string]: any }, | |
555 | + translateFn?: (key: string) => string) { | |
527 | 556 | let res = ''; |
528 | 557 | try { |
529 | 558 | if (template.match(/<link-act/g)) { |
530 | - template = template.replace(/<link-act/g, '<a').replace(/link-act>/g, 'a>').replace(/name=(\'|")(.*?)(\'|")/g, `class='tb-custom-action' id='$2'`); | |
559 | + template = template.replace(/<link-act/g, '<a').replace(/link-act>/g, 'a>') | |
560 | + .replace(/name=(\'|")(.*?)(\'|")/g, `class='tb-custom-action' id='$2'`); | |
531 | 561 | } |
532 | 562 | if (translateFn) { |
533 | 563 | template = translateFn(template); |
534 | 564 | } |
565 | + template = createLabelFromDatasource(data.$datasource, template); | |
535 | 566 | const formatted = template.match(/\$\{([^}]*)\:\d*\}/g); |
536 | 567 | if (formatted) |
537 | 568 | formatted.forEach(value => { | ... | ... |
... | ... | @@ -33,7 +33,7 @@ import { Datasource, WidgetActionDescriptor, WidgetConfig } from '@shared/models |
33 | 33 | import { IWidgetSubscription } from '@core/api/widget-api.models'; |
34 | 34 | import { UtilsService } from '@core/services/utils.service'; |
35 | 35 | import { TranslateService } from '@ngx-translate/core'; |
36 | -import { deepClone, isDefined, isNumber } from '@core/utils'; | |
36 | +import { deepClone, isDefined, isNumber, createLabelFromDatasource } from '@core/utils'; | |
37 | 37 | import cssjs from '@core/css/css'; |
38 | 38 | import { PageLink } from '@shared/models/page/page-link'; |
39 | 39 | import { Direction, SortOrder, sortOrderFromString } from '@shared/models/page/sort-order'; |
... | ... | @@ -282,7 +282,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit, |
282 | 282 | alarmsTitle = this.translate.instant('alarm.alarms'); |
283 | 283 | } |
284 | 284 | |
285 | - this.ctx.widgetTitle = this.utils.createLabelFromDatasource(this.alarmSource, alarmsTitle); | |
285 | + this.ctx.widgetTitle = createLabelFromDatasource(this.alarmSource, alarmsTitle); | |
286 | 286 | |
287 | 287 | this.enableSelection = isDefined(this.settings.enableSelection) ? this.settings.enableSelection : true; |
288 | 288 | if (!this.allowAcknowledgment && !this.allowClear) { | ... | ... |
... | ... | @@ -39,7 +39,7 @@ import { |
39 | 39 | import { IWidgetSubscription } from '@core/api/widget-api.models'; |
40 | 40 | import { UtilsService } from '@core/services/utils.service'; |
41 | 41 | import { TranslateService } from '@ngx-translate/core'; |
42 | -import { deepClone, isDefined, isNumber } from '@core/utils'; | |
42 | +import { deepClone, isDefined, isNumber, createLabelFromDatasource } from '@core/utils'; | |
43 | 43 | import cssjs from '@core/css/css'; |
44 | 44 | import { PageLink } from '@shared/models/page/page-link'; |
45 | 45 | import { Direction, SortOrder, sortOrderFromString } from '@shared/models/page/sort-order'; |
... | ... | @@ -210,7 +210,7 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni |
210 | 210 | } |
211 | 211 | |
212 | 212 | const datasource = this.subscription.datasources[0]; |
213 | - this.ctx.widgetTitle = this.utils.createLabelFromDatasource(datasource, entitiesTitle); | |
213 | + this.ctx.widgetTitle = createLabelFromDatasource(datasource, entitiesTitle); | |
214 | 214 | |
215 | 215 | this.searchAction.show = isDefined(this.settings.enableSearch) ? this.settings.enableSearch : true; |
216 | 216 | this.displayPagination = isDefined(this.settings.displayPagination) ? this.settings.displayPagination : true; | ... | ... |
... | ... | @@ -26,6 +26,7 @@ import { filter } from 'rxjs/operators'; |
26 | 26 | import { Polyline } from './polyline'; |
27 | 27 | import { Polygon } from './polygon'; |
28 | 28 | import { DatasourceData } from '@app/shared/models/widget.models'; |
29 | +import { safeExecute } from '@app/core/utils'; | |
29 | 30 | |
30 | 31 | export default abstract class LeafletMap { |
31 | 32 | |
... | ... | @@ -87,12 +88,14 @@ export default abstract class LeafletMap { |
87 | 88 | if (this.options.draggableMarker) { |
88 | 89 | let mousePositionOnMap: L.LatLng; |
89 | 90 | let addMarker: L.Control; |
90 | - this.map.on('mouseup', (e: L.LeafletMouseEvent) => { | |
91 | + this.map.on('mousemove', (e: L.LeafletMouseEvent) => { | |
91 | 92 | mousePositionOnMap = e.latlng; |
92 | 93 | }); |
93 | 94 | const dragListener = (e: L.DragEndEvent) => { |
94 | 95 | if (e.type === 'dragend' && mousePositionOnMap) { |
95 | - const newMarker = L.marker(mousePositionOnMap).addTo(this.map); | |
96 | + const icon = new L.Icon.Default(); | |
97 | + icon.options.shadowSize = [0, 0]; | |
98 | + const newMarker = L.marker(mousePositionOnMap, { icon }).addTo(this.map); | |
96 | 99 | const datasourcesList = document.createElement('div'); |
97 | 100 | const customLatLng = this.convertToCustomFormat(mousePositionOnMap); |
98 | 101 | this.datasources.forEach(ds => { |
... | ... | @@ -195,15 +198,18 @@ export default abstract class LeafletMap { |
195 | 198 | |
196 | 199 | fitBounds(bounds: LatLngBounds, useDefaultZoom = false, padding?: LatLngTuple) { |
197 | 200 | if (bounds.isValid()) { |
198 | - if ((!this.options.fitMapBounds || useDefaultZoom) && this.options.defaultZoomLevel) { | |
201 | + if ((!this.options.fitMapBounds || this.options.useDefaultCenterPosition) && this.options.defaultZoomLevel) { | |
199 | 202 | this.map.setZoom(this.options.defaultZoomLevel, { animate: false }); |
200 | - this.map.panTo(bounds.getCenter(), { animate: false }); | |
203 | + this.map.panTo(this.options.defaultCenterPosition, { animate: false }); | |
201 | 204 | } else { |
202 | 205 | this.map.once('zoomend', () => { |
203 | 206 | if (!this.options.defaultZoomLevel && this.map.getZoom() > this.options.minZoomLevel) { |
204 | 207 | this.map.setZoom(this.options.minZoomLevel, { animate: false }); |
205 | 208 | } |
206 | 209 | }); |
210 | + if (this.options.useDefaultCenterPosition) { | |
211 | + bounds = bounds.extend(this.options.defaultCenterPosition); | |
212 | + } | |
207 | 213 | this.map.fitBounds(bounds, { padding: padding || [50, 50], animate: false }); |
208 | 214 | } |
209 | 215 | this.bounds = bounds; |
... | ... | @@ -231,8 +237,16 @@ export default abstract class LeafletMap { |
231 | 237 | updateMarkers(markersData) { |
232 | 238 | markersData.filter(mdata => !!this.convertPosition(mdata)).forEach(data => { |
233 | 239 | if (data.rotationAngle || data.rotationAngle === 0) { |
240 | + const currentImage = this.options.useMarkerImageFunction ? | |
241 | + safeExecute(this.options.markerImageFunction, | |
242 | + [data, this.options.markerImages, markersData, data.dsIndex]) : this.options.currentImage; | |
243 | + const style = currentImage ? 'background-image: url(' + currentImage.url + ');' : ''; | |
234 | 244 | this.options.icon = L.divIcon({ |
235 | - html: `<div class="arrow" style="transform: translate(-10px, -10px) rotate(${data.rotationAngle}deg);"><div>` | |
245 | + html: `<div class="arrow" | |
246 | + style="transform: translate(-10px, -10px); | |
247 | + ${style} | |
248 | + rotate(${data.rotationAngle}deg); | |
249 | + "><div>` | |
236 | 250 | }) |
237 | 251 | } |
238 | 252 | else { |
... | ... | @@ -335,31 +349,28 @@ export default abstract class LeafletMap { |
335 | 349 | data.data = JSON.parse(data.data[0][1]) as LatLngTuple[]; |
336 | 350 | } |
337 | 351 | if (this.polygons.get(data.datasource.entityName)) { |
338 | - this.updatePolygon(data.datasource.entityName, data.data, polyData, this.options); | |
352 | + this.updatePolygon(data, polyData, this.options); | |
339 | 353 | } |
340 | 354 | else { |
341 | - this.createPolygon(data.datasource.entityName, data.data, polyData, this.options); | |
355 | + this.createPolygon(data, polyData, this.options); | |
342 | 356 | } |
343 | 357 | } |
344 | 358 | }); |
345 | 359 | } |
346 | 360 | |
347 | - createPolygon(key: string, data: LatLngTuple[], dataSources: DatasourceData[], settings: PolygonSettings) { | |
361 | + createPolygon(polyData: DatasourceData, dataSources: DatasourceData[], settings: PolygonSettings) { | |
348 | 362 | this.ready$.subscribe(() => { |
349 | - const polygon = new Polygon(this.map, data, dataSources, settings); | |
363 | + const polygon = new Polygon(this.map, polyData, dataSources, settings); | |
350 | 364 | const bounds = this.bounds.extend(polygon.leafletPoly.getBounds()); |
351 | - if (bounds.isValid()) { | |
352 | - this.map.fitBounds(bounds); | |
353 | - this.bounds = bounds; | |
354 | - } | |
355 | - this.polygons.set(key, polygon); | |
365 | + this.fitBounds(bounds); | |
366 | + this.polygons.set(polyData.datasource.entityName, polygon); | |
356 | 367 | }); |
357 | 368 | } |
358 | 369 | |
359 | - updatePolygon(key: string, data: LatLngTuple[], dataSources: DatasourceData[], settings: PolygonSettings) { | |
370 | + updatePolygon(polyData: DatasourceData, dataSources: DatasourceData[], settings: PolygonSettings) { | |
360 | 371 | this.ready$.subscribe(() => { |
361 | - const poly = this.polygons.get(key); | |
362 | - poly.updatePolygon(data, dataSources, settings); | |
372 | + const poly = this.polygons.get(polyData.datasource.entityName); | |
373 | + poly.updatePolygon(polyData.data, dataSources, settings); | |
363 | 374 | this.fitBounds(poly.leafletPoly.getBounds()); |
364 | 375 | }); |
365 | 376 | } | ... | ... |
... | ... | @@ -111,9 +111,13 @@ export type PolygonSettings = { |
111 | 111 | polygonStrokeWeight: number; |
112 | 112 | polygonStrokeColor: string; |
113 | 113 | polygonColor: string; |
114 | + showPolygonTooltip: boolean; | |
114 | 115 | autocloseTooltip: boolean; |
116 | + tooltipFunction: GenericFunction; | |
115 | 117 | showTooltipAction: string; |
116 | 118 | tooltipAction: object; |
119 | + tooltipPattern: string; | |
120 | + useTooltipFunction: boolean; | |
117 | 121 | polygonClick: { [name: string]: actionsHandler }; |
118 | 122 | polygonColorFunction?: GenericFunction; |
119 | 123 | } | ... | ... |
... | ... | @@ -16,8 +16,9 @@ |
16 | 16 | |
17 | 17 | import L, { LatLngExpression, LatLngTuple } from 'leaflet'; |
18 | 18 | import { createTooltip } from './maps-utils'; |
19 | -import { PolygonSettings } from './map-models'; | |
19 | +import { PolygonSettings, FormattedData } from './map-models'; | |
20 | 20 | import { DatasourceData } from '@app/shared/models/widget.models'; |
21 | +import { safeExecute, parseWithTranslation } from '@app/core/utils'; | |
21 | 22 | |
22 | 23 | export class Polygon { |
23 | 24 | |
... | ... | @@ -26,8 +27,8 @@ export class Polygon { |
26 | 27 | data; |
27 | 28 | dataSources; |
28 | 29 | |
29 | - constructor(public map, coordinates, dataSources, settings: PolygonSettings, onClickListener?) { | |
30 | - this.leafletPoly = L.polygon(coordinates, { | |
30 | + constructor(public map, polyData: DatasourceData, dataSources, private settings: PolygonSettings, onClickListener?) { | |
31 | + this.leafletPoly = L.polygon(polyData.data, { | |
31 | 32 | fill: true, |
32 | 33 | fillColor: settings.polygonColor, |
33 | 34 | color: settings.polygonStrokeColor, |
... | ... | @@ -35,19 +36,29 @@ export class Polygon { |
35 | 36 | fillOpacity: settings.polygonOpacity, |
36 | 37 | opacity: settings.polygonStrokeOpacity |
37 | 38 | }).addTo(this.map); |
38 | - | |
39 | - if (settings.showTooltip) { | |
39 | + this.dataSources = dataSources; | |
40 | + this.data = polyData; | |
41 | + if (settings.showPolygonTooltip) { | |
40 | 42 | this.tooltip = createTooltip(this.leafletPoly, settings); |
43 | + this.updateTooltip(polyData); | |
41 | 44 | } |
42 | 45 | if (onClickListener) { |
43 | 46 | this.leafletPoly.on('click', onClickListener); |
44 | 47 | } |
45 | 48 | } |
46 | 49 | |
50 | + updateTooltip(data: DatasourceData) { | |
51 | + const pattern = this.settings.useTooltipFunction ? | |
52 | + safeExecute(this.settings.tooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) : this.settings.tooltipPattern; | |
53 | + this.tooltip.setContent(parseWithTranslation.parseTemplate(pattern, data, true)); | |
54 | + } | |
55 | + | |
47 | 56 | updatePolygon(data: LatLngTuple[], dataSources: DatasourceData[], settings: PolygonSettings) { |
48 | 57 | this.data = data; |
49 | 58 | this.dataSources = dataSources; |
50 | 59 | this.leafletPoly.setLatLngs(data); |
60 | + if (settings.showPolygonTooltip) | |
61 | + this.updateTooltip(this.data); | |
51 | 62 | this.updatePolygonColor(settings); |
52 | 63 | } |
53 | 64 | ... | ... |
... | ... | @@ -477,6 +477,11 @@ export const mapPolygonSchema = |
477 | 477 | type: 'number', |
478 | 478 | default: 1 |
479 | 479 | }, |
480 | + showPolygonTooltip: { | |
481 | + title: 'Show polygon tooltip', | |
482 | + type: 'boolean', | |
483 | + default: false | |
484 | + }, | |
480 | 485 | usePolygonColorFunction: { |
481 | 486 | title: 'Use polygon color function', |
482 | 487 | type: 'boolean', |
... | ... | @@ -501,7 +506,7 @@ export const mapPolygonSchema = |
501 | 506 | key: 'polygonStrokeColor', |
502 | 507 | type: 'color' |
503 | 508 | }, |
504 | - 'polygonStrokeOpacity', 'polygonStrokeWeight', 'usePolygonColorFunction', | |
509 | + 'polygonStrokeOpacity', 'polygonStrokeWeight', 'usePolygonColorFunction', 'showPolygonTooltip', | |
505 | 510 | { |
506 | 511 | key: 'polygonColorFunction', |
507 | 512 | type: 'javascript' |
... | ... | @@ -1137,7 +1142,7 @@ export const tripAnimationSchema = { |
1137 | 1142 | rotationAngle: { |
1138 | 1143 | title: 'Set additional rotation angle for marker (deg)', |
1139 | 1144 | type: 'number', |
1140 | - default: 180 | |
1145 | + default: 0 | |
1141 | 1146 | }, |
1142 | 1147 | useMarkerImageFunction: { |
1143 | 1148 | title: 'Use marker image function', | ... | ... |
... | ... | @@ -24,7 +24,7 @@ import { UtilsService } from '@core/services/utils.service'; |
24 | 24 | import { TranslateService } from '@ngx-translate/core'; |
25 | 25 | import { DataKey, Datasource, DatasourceData, DatasourceType, WidgetConfig } from '@shared/models/widget.models'; |
26 | 26 | import { IWidgetSubscription } from '@core/api/widget-api.models'; |
27 | -import { isDefined, isEqual, isUndefined } from '@core/utils'; | |
27 | +import { isDefined, isEqual, isUndefined, createLabelFromDatasource } from '@core/utils'; | |
28 | 28 | import { EntityType } from '@shared/models/entity-type.models'; |
29 | 29 | import * as _moment from 'moment'; |
30 | 30 | import { FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms'; |
... | ... | @@ -331,7 +331,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni |
331 | 331 | } |
332 | 332 | |
333 | 333 | public getGroupTitle(datasource: Datasource): string { |
334 | - return this.utils.createLabelFromDatasource(datasource, this.settings.groupTitle); | |
334 | + return createLabelFromDatasource(datasource, this.settings.groupTitle); | |
335 | 335 | } |
336 | 336 | |
337 | 337 | public visibleKeys(source: MultipleInputWidgetSource): MultipleInputWidgetDataKey[] { | ... | ... |