Commit 09a446bdad73556293f2a74bce0286df85cb0d4f

Authored by Artem Halushko
1 parent e77754a6

label fix & tooltips support

@@ -517,4 +517,51 @@ export function parseFunction(source: string, params: string[] = []): Function { @@ -517,4 +517,51 @@ export function parseFunction(source: string, params: string[] = []): Function {
517 } 517 }
518 } 518 }
519 return res; 519 return res;
  520 +}
  521 +
  522 +export function parseTemplate(template, data) {
  523 + function formatValue(value, pattern) {
  524 +
  525 + }
  526 +
  527 + let res = '';
  528 + try {
  529 + let variables = '';
  530 + let expressions = template
  531 + .match(/\{(.*?)\}/g) // find expressions
  532 + .map(exp => exp.replace(/{|}/g, '')) // remove brackets
  533 + .map(exp => exp.split(':'))
  534 + .filter(arr => !!arr[1]) //filter expressions without format
  535 + .reduce((res, current) => {
  536 + res[current[0]] = current[1];
  537 + return res;
  538 + }, {});
  539 +
  540 + for (let key in data) {
  541 + if (!key.includes('|'))
  542 + variables += `let ${key} = '${expressions[key] ? padValue(data[key], +expressions[key]) : data[key]}';`;
  543 + }
  544 + template = template.replace(/:\d+}/g, '}');
  545 + res = safeExecute(parseFunction(variables + 'return' + '`' + template + '`'));
  546 + }
  547 + catch (ex) {
  548 + }
  549 + return res;
  550 +}
  551 +
  552 +export function padValue(val: any, dec: number): string {
  553 + let strVal;
  554 + let n;
  555 +
  556 + val = parseFloat(val);
  557 + n = (val < 0);
  558 + val = Math.abs(val);
  559 +
  560 + if (dec > 0) {
  561 + strVal = val.toFixed(dec).toString()
  562 + } else {
  563 + strVal = Math.round(val).toString();
  564 + }
  565 + strVal = (n ? '-' : '') + strVal;
  566 + return strVal;
520 } 567 }
@@ -20,7 +20,7 @@ import BaseGauge = CanvasGauges.BaseGauge; @@ -20,7 +20,7 @@ import BaseGauge = CanvasGauges.BaseGauge;
20 import { FontStyle, FontWeight } from '@home/components/widget/lib/settings.models'; 20 import { FontStyle, FontWeight } from '@home/components/widget/lib/settings.models';
21 import * as tinycolor_ from 'tinycolor2'; 21 import * as tinycolor_ from 'tinycolor2';
22 import { ColorFormats } from 'tinycolor2'; 22 import { ColorFormats } from 'tinycolor2';
23 -import { isDefined, isString, isUndefined } from '@core/utils'; 23 +import { isDefined, isString, isUndefined, padValue } from '@core/utils';
24 24
25 const tinycolor = tinycolor_; 25 const tinycolor = tinycolor_;
26 26
@@ -765,24 +765,6 @@ function drawDigitalMinMax(context: DigitalGaugeCanvasRenderingContext2D, option @@ -765,24 +765,6 @@ function drawDigitalMinMax(context: DigitalGaugeCanvasRenderingContext2D, option
765 drawText(context, options, 'MinMax', options.maxValue+'', maxX, maxY); 765 drawText(context, options, 'MinMax', options.maxValue+'', maxX, maxY);
766 } 766 }
767 767
768 -function padValue(val: any, options: CanvasDigitalGaugeOptions): string {  
769 - const dec = options.valueDec;  
770 - let strVal;  
771 - let n;  
772 -  
773 - val = parseFloat(val);  
774 - n = (val < 0);  
775 - val = Math.abs(val);  
776 -  
777 - if (dec > 0) {  
778 - strVal = val.toFixed(dec).toString()  
779 - } else {  
780 - strVal = Math.round(val).toString();  
781 - }  
782 - strVal = (n ? '-' : '') + strVal;  
783 - return strVal;  
784 -}  
785 -  
786 function drawDigitalValue(context: DigitalGaugeCanvasRenderingContext2D, options: CanvasDigitalGaugeOptions, value: any) { 768 function drawDigitalValue(context: DigitalGaugeCanvasRenderingContext2D, options: CanvasDigitalGaugeOptions, value: any) {
787 if (options.hideValue) return; 769 if (options.hideValue) return;
788 770
@@ -792,7 +774,7 @@ function drawDigitalValue(context: DigitalGaugeCanvasRenderingContext2D, options @@ -792,7 +774,7 @@ function drawDigitalValue(context: DigitalGaugeCanvasRenderingContext2D, options
792 const textX = Math.round(baseX + width / 2); 774 const textX = Math.round(baseX + width / 2);
793 const textY = valueY; 775 const textY = valueY;
794 776
795 - let text = options.valueText || padValue(value, options); 777 + let text = options.valueText || padValue(value, options.valueDec);
796 text += options.symbol; 778 text += options.symbol;
797 779
798 context.save(); 780 context.save();
@@ -98,26 +98,6 @@ export default abstract class LeafletMap { @@ -98,26 +98,6 @@ export default abstract class LeafletMap {
98 this.map.invalidateSize(true); 98 this.map.invalidateSize(true);
99 } 99 }
100 100
101 - createTooltip(marker, dsIndex, settings, markerArgs) {  
102 - var popup = L.popup();  
103 - popup.setContent('');  
104 - marker.bindPopup(popup, { autoClose: settings.autocloseTooltip, closeOnClick: false });  
105 - if (settings.displayTooltipAction == 'hover') {  
106 - marker.off('click');  
107 - marker.on('mouseover', function () {  
108 - this.openPopup();  
109 - });  
110 - marker.on('mouseout', function () {  
111 - this.closePopup();  
112 - });  
113 - }  
114 - return {  
115 - markerArgs: markerArgs,  
116 - popup: popup,  
117 - locationSettings: settings,  
118 - dsIndex: dsIndex  
119 - }  
120 - }  
121 101
122 onResize() { 102 onResize() {
123 103
@@ -169,6 +149,9 @@ export default abstract class LeafletMap { @@ -169,6 +149,9 @@ export default abstract class LeafletMap {
169 if (!location.equals(marker.location)) { 149 if (!location.equals(marker.location)) {
170 marker.updateMarkerPosition(location); 150 marker.updateMarkerPosition(location);
171 } 151 }
  152 + if (settings.showTooltip) {
  153 + marker.updateMarkerTooltip(data);
  154 + }
172 marker.setDataSources(data, dataSources); 155 marker.setDataSources(data, dataSources);
173 marker.updateMarkerIcon(settings); 156 marker.updateMarkerIcon(settings);
174 } 157 }
@@ -207,11 +190,11 @@ export default abstract class LeafletMap { @@ -207,11 +190,11 @@ export default abstract class LeafletMap {
207 updatePolyline(data, dataSources, settings) { 190 updatePolyline(data, dataSources, settings) {
208 this.ready$.subscribe(() => { 191 this.ready$.subscribe(() => {
209 this.poly.updatePolyline(settings, data, dataSources); 192 this.poly.updatePolyline(settings, data, dataSources);
210 - const bounds = this.bounds.extend(this.poly.leafletPoly.getBounds());  
211 - if (bounds.isValid()) {  
212 - this.map.fitBounds(bounds);  
213 - this.bounds = bounds;  
214 - } 193 + /* const bounds = this.bounds.extend(this.poly.leafletPoly.getBounds());
  194 + if (bounds.isValid()) {
  195 + this.map.fitBounds(bounds);
  196 + this.bounds = bounds;
  197 + }*/
215 }); 198 });
216 } 199 }
217 } 200 }
@@ -46,10 +46,11 @@ export enum MapProviders { @@ -46,10 +46,11 @@ export enum MapProviders {
46 } 46 }
47 47
48 export interface MarkerSettings extends MapOptions { 48 export interface MarkerSettings extends MapOptions {
  49 + tooltipPattern?: any;
49 icon?: any; 50 icon?: any;
50 showLabel?: boolean, 51 showLabel?: boolean,
51 draggable?: boolean, 52 draggable?: boolean,
52 - displayTooltip?: boolean, 53 + showTooltip?: boolean,
53 color?: string, 54 color?: string,
54 currentImage?: string; 55 currentImage?: string;
55 useMarkerImageFunction?: boolean, 56 useMarkerImageFunction?: boolean,
@@ -40,7 +40,7 @@ export class MapWidgetController implements MapWidgetInterface { @@ -40,7 +40,7 @@ export class MapWidgetController implements MapWidgetInterface {
40 schema; 40 schema;
41 data; 41 data;
42 42
43 - constructor(public mapProvider: MapProviders, private drawRoutes, ctx, $element) { 43 + constructor(public mapProvider: MapProviders, private drawRoutes, public ctx, $element) {
44 if (this.map) { 44 if (this.map) {
45 this.map.map.remove(); 45 this.map.map.remove();
46 delete this.map; 46 delete this.map;
@@ -73,6 +73,7 @@ export class MapWidgetController implements MapWidgetInterface { @@ -73,6 +73,7 @@ export class MapWidgetController implements MapWidgetInterface {
73 colorFunction: parseFunction(settings.colorFunction, functionParams), 73 colorFunction: parseFunction(settings.colorFunction, functionParams),
74 polygonColorFunction: parseFunction(settings.polygonColorFunction, functionParams), 74 polygonColorFunction: parseFunction(settings.polygonColorFunction, functionParams),
75 markerImageFunction: parseFunction(settings.markerImageFunction, ['data', 'images', 'dsData', 'dsIndex']), 75 markerImageFunction: parseFunction(settings.markerImageFunction, ['data', 'images', 'dsData', 'dsIndex']),
  76 + labelColor: this.ctx.widgetConfig.color,
76 tooltipPattern: settings.tooltipPattern || 77 tooltipPattern: settings.tooltipPattern ||
77 "<b>${entityName}</b><br/><br/><b>Latitude:</b> ${" + settings.latKeyName + ":7}<br/><b>Longitude:</b> ${" + settings.lngKeyName + ":7}", 78 "<b>${entityName}</b><br/><br/><b>Latitude:</b> ${" + settings.latKeyName + ":7}<br/><b>Longitude:</b> ${" + settings.lngKeyName + ":7}",
78 defaultCenterPosition: settings?.defaultCenterPosition?.split(',') || [0, 0], 79 defaultCenterPosition: settings?.defaultCenterPosition?.split(',') || [0, 0],
@@ -120,7 +121,6 @@ export class MapWidgetController implements MapWidgetInterface { @@ -120,7 +121,6 @@ export class MapWidgetController implements MapWidgetInterface {
120 //const providerInfo = providerSets[mapProvider]; 121 //const providerInfo = providerSets[mapProvider];
121 let schema = initSchema(); 122 let schema = initSchema();
122 addToSchema(schema,this.getProvidersSchema()); 123 addToSchema(schema,this.getProvidersSchema());
123 -  
124 addGroupInfo(schema, "Map Provider Settings"); 124 addGroupInfo(schema, "Map Provider Settings");
125 addToSchema(schema, commonMapSettingsSchema); 125 addToSchema(schema, commonMapSettingsSchema);
126 addGroupInfo(schema, "Common Map Settings"); 126 addGroupInfo(schema, "Common Map Settings");
@@ -31,12 +31,12 @@ export function createTooltip(target, settings, targetArgs?) { @@ -31,12 +31,12 @@ export function createTooltip(target, settings, targetArgs?) {
31 this.closePopup(); 31 this.closePopup();
32 }); 32 });
33 } 33 }
34 - return { 34 + return popup/*{
35 markerArgs: targetArgs, 35 markerArgs: targetArgs,
36 popup: popup, 36 popup: popup,
37 locationSettings: settings, 37 locationSettings: settings,
38 dsIndex: settings.dsIndex 38 dsIndex: settings.dsIndex
39 - }; 39 + };*/
40 } 40 }
41 41
42 42
@@ -22,7 +22,10 @@ @@ -22,7 +22,10 @@
22 background-position: center center; 22 background-position: center center;
23 } 23 }
24 24
25 -.leaflet-div-icon {  
26 - background: none; 25 +.leaflet-div-icon,
  26 +.tb-marker-label,
  27 +.tb-marker-label:before {
27 border: none; 28 border: none;
  29 + background: none;
  30 + box-shadow: none;
28 } 31 }
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 16
17 import L from 'leaflet'; 17 import L from 'leaflet';
18 import { MarkerSettings } from './map-models'; 18 import { MarkerSettings } from './map-models';
19 -import { aspectCache, safeExecute, parseFunction } from '@app/core/utils'; 19 +import { aspectCache, safeExecute, parseTemplate } from '@app/core/utils';
20 import { createTooltip } from './maps-utils'; 20 import { createTooltip } from './maps-utils';
21 21
22 export class Marker { 22 export class Marker {
@@ -32,24 +32,21 @@ export class Marker { @@ -32,24 +32,21 @@ export class Marker {
32 constructor(private map: L.Map, location: L.LatLngExpression, public settings: MarkerSettings, data, dataSources, onClickListener?, markerArgs?, onDragendListener?) { 32 constructor(private map: L.Map, location: L.LatLngExpression, public settings: MarkerSettings, data, dataSources, onClickListener?, markerArgs?, onDragendListener?) {
33 //this.map = map; 33 //this.map = map;
34 this.location = location; 34 this.location = location;
35 - this.setDataSources(data, dataSources) 35 + this.setDataSources(data, dataSources);
36 this.leafletMarker = L.marker(location, { 36 this.leafletMarker = L.marker(location, {
37 draggable: settings.draggable 37 draggable: settings.draggable
38 }); 38 });
39 39
40 this.createMarkerIcon((iconInfo) => { 40 this.createMarkerIcon((iconInfo) => {
41 this.leafletMarker.setIcon(iconInfo.icon); 41 this.leafletMarker.setIcon(iconInfo.icon);
42 - if (settings.showLabel) {  
43 - this.tooltipOffset = [0, -iconInfo.size[1] + 10];  
44 - // this.updateMarkerLabel(settings)  
45 - }  
46 -  
47 - this.leafletMarker.addTo(map)  
48 - }  
49 - ); 42 + this.tooltipOffset = [0, -iconInfo.size[1] + 10];
  43 + this.updateMarkerLabel(settings);
  44 + this.leafletMarker.addTo(map);
  45 + });
50 46
51 - if (settings.displayTooltip) { 47 + if (settings.showTooltip) {
52 this.tooltip = createTooltip(this.leafletMarker, settings, markerArgs); 48 this.tooltip = createTooltip(this.leafletMarker, settings, markerArgs);
  49 + this.tooltip.setContent(parseTemplate(this.settings.tooltipPattern, data));
53 } 50 }
54 51
55 if (onClickListener) { 52 if (onClickListener) {
@@ -67,35 +64,22 @@ export class Marker { @@ -67,35 +64,22 @@ export class Marker {
67 this.dataSources = dataSources; 64 this.dataSources = dataSources;
68 } 65 }
69 66
  67 + updateMarkerTooltip(data) {
  68 + this.tooltip.setContent(parseTemplate(this.settings.tooltipPattern, data));
  69 + }
  70 +
70 updateMarkerPosition(position: L.LatLngExpression) { 71 updateMarkerPosition(position: L.LatLngExpression) {
71 this.leafletMarker.setLatLng(position); 72 this.leafletMarker.setLatLng(position);
72 } 73 }
73 74
74 updateMarkerLabel(settings) { 75 updateMarkerLabel(settings) {
75 -  
76 - function getText(template, data) {  
77 - let res = null;  
78 - try {  
79 - let variables = '';  
80 - for (let key in data) {  
81 - if (!key.includes('|'))  
82 - variables += `var ${key} = '${data[key]}';`;  
83 - }  
84 - res = safeExecute(parseFunction(variables + 'return' + '`' + template + '`'));  
85 - }  
86 - catch (ex) {  
87 - }  
88 - return res;  
89 - }  
90 -  
91 -  
92 this.leafletMarker.unbindTooltip(); 76 this.leafletMarker.unbindTooltip();
  77 +
93 if (settings.showLabel) { 78 if (settings.showLabel) {
94 if (settings.useLabelFunction) { 79 if (settings.useLabelFunction) {
95 settings.labelText = safeExecute(settings.labelFunction, [this.data, this.dataSources, this.data.dsIndex]) 80 settings.labelText = safeExecute(settings.labelFunction, [this.data, this.dataSources, this.data.dsIndex])
96 } 81 }
97 - else settings.labelText = getText(settings.label, this.data);  
98 - 82 + else settings.labelText = parseTemplate(settings.label, this.data);
99 this.leafletMarker.bindTooltip(`<div style="color: ${settings.labelColor};"><b>${settings.labelText}</b></div>`, 83 this.leafletMarker.bindTooltip(`<div style="color: ${settings.labelColor};"><b>${settings.labelText}</b></div>`,
100 { className: 'tb-marker-label', permanent: true, direction: 'top', offset: this.tooltipOffset }); 84 { className: 'tb-marker-label', permanent: true, direction: 'top', offset: this.tooltipOffset });
101 } 85 }
@@ -110,10 +94,8 @@ export class Marker { @@ -110,10 +94,8 @@ export class Marker {
110 updateMarkerIcon(settings) { 94 updateMarkerIcon(settings) {
111 this.createMarkerIcon((iconInfo) => { 95 this.createMarkerIcon((iconInfo) => {
112 this.leafletMarker.setIcon(iconInfo.icon); 96 this.leafletMarker.setIcon(iconInfo.icon);
113 - if (settings.showLabel) {  
114 - this.tooltipOffset = [0, -iconInfo.size[1] + 10];  
115 - this.updateMarkerLabel(settings)  
116 - } 97 + this.tooltipOffset = [0, -iconInfo.size[1] + 10];
  98 + this.updateMarkerLabel(settings);
117 }); 99 });
118 } 100 }
119 101
@@ -121,7 +103,7 @@ export class Marker { @@ -121,7 +103,7 @@ export class Marker {
121 103
122 if (this.settings.icon) { 104 if (this.settings.icon) {
123 onMarkerIconReady({ 105 onMarkerIconReady({
124 - size: [30,30], 106 + size: [30, 30],
125 icon: this.settings.icon, 107 icon: this.settings.icon,
126 }); 108 });
127 return; 109 return;
@@ -130,8 +112,8 @@ export class Marker { @@ -130,8 +112,8 @@ export class Marker {
130 let currentImage = this.settings.useMarkerImageFunction ? 112 let currentImage = this.settings.useMarkerImageFunction ?
131 safeExecute(this.settings.markerImageFunction, 113 safeExecute(this.settings.markerImageFunction,
132 [this.data, this.settings.markerImages, this.dataSources, this.data.dsIndex]) : this.settings.currentImage; 114 [this.data, this.settings.markerImages, this.dataSources, this.data.dsIndex]) : this.settings.currentImage;
133 -  
134 - 115 +
  116 +
135 if (currentImage && currentImage.url) { 117 if (currentImage && currentImage.url) {
136 aspectCache(currentImage.url).subscribe( 118 aspectCache(currentImage.url).subscribe(
137 (aspect) => { 119 (aspect) => {
@@ -34,7 +34,7 @@ export class Polygon { @@ -34,7 +34,7 @@ export class Polygon {
34 opacity: settings.polygonStrokeOpacity 34 opacity: settings.polygonStrokeOpacity
35 }).addTo(this.map); 35 }).addTo(this.map);
36 36
37 - if (settings.displayTooltip) { 37 + if (settings.showTooltip) {
38 this.tooltip = createTooltip(this.leafletPoly, location.dsIndex, settings); 38 this.tooltip = createTooltip(this.leafletPoly, location.dsIndex, settings);
39 } 39 }
40 if (onClickListener) { 40 if (onClickListener) {
@@ -48,8 +48,9 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { @@ -48,8 +48,9 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
48 this.widgetConfig = this.ctx.widgetConfig; 48 this.widgetConfig = this.ctx.widgetConfig;
49 const settings = { 49 const settings = {
50 normalizationStep: 1000, 50 normalizationStep: 1000,
  51 + showLabel: false,
51 buttonColor: tinycolor(this.widgetConfig.color).setAlpha(0.54).toRgbString(), 52 buttonColor: tinycolor(this.widgetConfig.color).setAlpha(0.54).toRgbString(),
52 - disabledButtonColor: tinycolor(this.widgetConfig.color).setAlpha(0.3).toRgbString(), 53 + disabledButtonColor: tinycolor(this.widgetConfig.color).setAlpha(0.3).toRgbString(),
53 rotationAngle: 0 54 rotationAngle: 0
54 } 55 }
55 this.settings = { ...settings, ...this.ctx.settings }; 56 this.settings = { ...settings, ...this.ctx.settings };
@@ -73,7 +74,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { @@ -73,7 +74,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
73 74
74 timeUpdated(time) { 75 timeUpdated(time) {
75 const currentPosition = this.interpolatedData.map(dataSource => dataSource[time]); 76 const currentPosition = this.interpolatedData.map(dataSource => dataSource[time]);
76 - this.mapWidget.map.updateMarkers(currentPosition); 77 + this.mapWidget.map.updateMarkers(currentPosition);
77 } 78 }
78 79
79 calculateIntervals() { 80 calculateIntervals() {
@@ -108,4 +108,3 @@ const tinycolor = tinycolor_; @@ -108,4 +108,3 @@ const tinycolor = tinycolor_;
108 (window as any).TbCanvasDigitalGauge = TbCanvasDigitalGauge; 108 (window as any).TbCanvasDigitalGauge = TbCanvasDigitalGauge;
109 (window as any).TbMapWidgetV2 = TbMapWidgetV2; 109 (window as any).TbMapWidgetV2 = TbMapWidgetV2;
110 (window as any).TbTripAnimationWidget = TbTripAnimationWidget; 110 (window as any).TbTripAnimationWidget = TbTripAnimationWidget;
111 -console.log("TbTripAnimationWidget", TbTripAnimationWidget)