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 517 }
518 518 }
519 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 }
\ No newline at end of file
... ...
... ... @@ -20,7 +20,7 @@ import BaseGauge = CanvasGauges.BaseGauge;
20 20 import { FontStyle, FontWeight } from '@home/components/widget/lib/settings.models';
21 21 import * as tinycolor_ from 'tinycolor2';
22 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 25 const tinycolor = tinycolor_;
26 26
... ... @@ -765,24 +765,6 @@ function drawDigitalMinMax(context: DigitalGaugeCanvasRenderingContext2D, option
765 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 768 function drawDigitalValue(context: DigitalGaugeCanvasRenderingContext2D, options: CanvasDigitalGaugeOptions, value: any) {
787 769 if (options.hideValue) return;
788 770
... ... @@ -792,7 +774,7 @@ function drawDigitalValue(context: DigitalGaugeCanvasRenderingContext2D, options
792 774 const textX = Math.round(baseX + width / 2);
793 775 const textY = valueY;
794 776
795   - let text = options.valueText || padValue(value, options);
  777 + let text = options.valueText || padValue(value, options.valueDec);
796 778 text += options.symbol;
797 779
798 780 context.save();
... ...
... ... @@ -98,26 +98,6 @@ export default abstract class LeafletMap {
98 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 102 onResize() {
123 103
... ... @@ -169,6 +149,9 @@ export default abstract class LeafletMap {
169 149 if (!location.equals(marker.location)) {
170 150 marker.updateMarkerPosition(location);
171 151 }
  152 + if (settings.showTooltip) {
  153 + marker.updateMarkerTooltip(data);
  154 + }
172 155 marker.setDataSources(data, dataSources);
173 156 marker.updateMarkerIcon(settings);
174 157 }
... ... @@ -207,11 +190,11 @@ export default abstract class LeafletMap {
207 190 updatePolyline(data, dataSources, settings) {
208 191 this.ready$.subscribe(() => {
209 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 }
\ No newline at end of file
... ...
... ... @@ -46,10 +46,11 @@ export enum MapProviders {
46 46 }
47 47
48 48 export interface MarkerSettings extends MapOptions {
  49 + tooltipPattern?: any;
49 50 icon?: any;
50 51 showLabel?: boolean,
51 52 draggable?: boolean,
52   - displayTooltip?: boolean,
  53 + showTooltip?: boolean,
53 54 color?: string,
54 55 currentImage?: string;
55 56 useMarkerImageFunction?: boolean,
... ...
... ... @@ -40,7 +40,7 @@ export class MapWidgetController implements MapWidgetInterface {
40 40 schema;
41 41 data;
42 42
43   - constructor(public mapProvider: MapProviders, private drawRoutes, ctx, $element) {
  43 + constructor(public mapProvider: MapProviders, private drawRoutes, public ctx, $element) {
44 44 if (this.map) {
45 45 this.map.map.remove();
46 46 delete this.map;
... ... @@ -73,6 +73,7 @@ export class MapWidgetController implements MapWidgetInterface {
73 73 colorFunction: parseFunction(settings.colorFunction, functionParams),
74 74 polygonColorFunction: parseFunction(settings.polygonColorFunction, functionParams),
75 75 markerImageFunction: parseFunction(settings.markerImageFunction, ['data', 'images', 'dsData', 'dsIndex']),
  76 + labelColor: this.ctx.widgetConfig.color,
76 77 tooltipPattern: settings.tooltipPattern ||
77 78 "<b>${entityName}</b><br/><br/><b>Latitude:</b> ${" + settings.latKeyName + ":7}<br/><b>Longitude:</b> ${" + settings.lngKeyName + ":7}",
78 79 defaultCenterPosition: settings?.defaultCenterPosition?.split(',') || [0, 0],
... ... @@ -120,7 +121,6 @@ export class MapWidgetController implements MapWidgetInterface {
120 121 //const providerInfo = providerSets[mapProvider];
121 122 let schema = initSchema();
122 123 addToSchema(schema,this.getProvidersSchema());
123   -
124 124 addGroupInfo(schema, "Map Provider Settings");
125 125 addToSchema(schema, commonMapSettingsSchema);
126 126 addGroupInfo(schema, "Common Map Settings");
... ...
... ... @@ -31,12 +31,12 @@ export function createTooltip(target, settings, targetArgs?) {
31 31 this.closePopup();
32 32 });
33 33 }
34   - return {
  34 + return popup/*{
35 35 markerArgs: targetArgs,
36 36 popup: popup,
37 37 locationSettings: settings,
38 38 dsIndex: settings.dsIndex
39   - };
  39 + };*/
40 40 }
41 41
42 42
... ...
... ... @@ -22,7 +22,10 @@
22 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 28 border: none;
  29 + background: none;
  30 + box-shadow: none;
28 31 }
... ...
... ... @@ -16,7 +16,7 @@
16 16
17 17 import L from 'leaflet';
18 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 20 import { createTooltip } from './maps-utils';
21 21
22 22 export class Marker {
... ... @@ -32,24 +32,21 @@ export class Marker {
32 32 constructor(private map: L.Map, location: L.LatLngExpression, public settings: MarkerSettings, data, dataSources, onClickListener?, markerArgs?, onDragendListener?) {
33 33 //this.map = map;
34 34 this.location = location;
35   - this.setDataSources(data, dataSources)
  35 + this.setDataSources(data, dataSources);
36 36 this.leafletMarker = L.marker(location, {
37 37 draggable: settings.draggable
38 38 });
39 39
40 40 this.createMarkerIcon((iconInfo) => {
41 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 48 this.tooltip = createTooltip(this.leafletMarker, settings, markerArgs);
  49 + this.tooltip.setContent(parseTemplate(this.settings.tooltipPattern, data));
53 50 }
54 51
55 52 if (onClickListener) {
... ... @@ -67,35 +64,22 @@ export class Marker {
67 64 this.dataSources = dataSources;
68 65 }
69 66
  67 + updateMarkerTooltip(data) {
  68 + this.tooltip.setContent(parseTemplate(this.settings.tooltipPattern, data));
  69 + }
  70 +
70 71 updateMarkerPosition(position: L.LatLngExpression) {
71 72 this.leafletMarker.setLatLng(position);
72 73 }
73 74
74 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 76 this.leafletMarker.unbindTooltip();
  77 +
93 78 if (settings.showLabel) {
94 79 if (settings.useLabelFunction) {
95 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 83 this.leafletMarker.bindTooltip(`<div style="color: ${settings.labelColor};"><b>${settings.labelText}</b></div>`,
100 84 { className: 'tb-marker-label', permanent: true, direction: 'top', offset: this.tooltipOffset });
101 85 }
... ... @@ -110,10 +94,8 @@ export class Marker {
110 94 updateMarkerIcon(settings) {
111 95 this.createMarkerIcon((iconInfo) => {
112 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 103
122 104 if (this.settings.icon) {
123 105 onMarkerIconReady({
124   - size: [30,30],
  106 + size: [30, 30],
125 107 icon: this.settings.icon,
126 108 });
127 109 return;
... ... @@ -130,8 +112,8 @@ export class Marker {
130 112 let currentImage = this.settings.useMarkerImageFunction ?
131 113 safeExecute(this.settings.markerImageFunction,
132 114 [this.data, this.settings.markerImages, this.dataSources, this.data.dsIndex]) : this.settings.currentImage;
133   -
134   -
  115 +
  116 +
135 117 if (currentImage && currentImage.url) {
136 118 aspectCache(currentImage.url).subscribe(
137 119 (aspect) => {
... ...
... ... @@ -34,7 +34,7 @@ export class Polygon {
34 34 opacity: settings.polygonStrokeOpacity
35 35 }).addTo(this.map);
36 36
37   - if (settings.displayTooltip) {
  37 + if (settings.showTooltip) {
38 38 this.tooltip = createTooltip(this.leafletPoly, location.dsIndex, settings);
39 39 }
40 40 if (onClickListener) {
... ...
... ... @@ -48,8 +48,9 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
48 48 this.widgetConfig = this.ctx.widgetConfig;
49 49 const settings = {
50 50 normalizationStep: 1000,
  51 + showLabel: false,
51 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 54 rotationAngle: 0
54 55 }
55 56 this.settings = { ...settings, ...this.ctx.settings };
... ... @@ -73,7 +74,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
73 74
74 75 timeUpdated(time) {
75 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 80 calculateIntervals() {
... ...
... ... @@ -108,4 +108,3 @@ const tinycolor = tinycolor_;
108 108 (window as any).TbCanvasDigitalGauge = TbCanvasDigitalGauge;
109 109 (window as any).TbMapWidgetV2 = TbMapWidgetV2;
110 110 (window as any).TbTripAnimationWidget = TbTripAnimationWidget;
111   -console.log("TbTripAnimationWidget", TbTripAnimationWidget)
... ...