Commit b05c94e9df3d4472cb02a5d4edc0c813020411aa

Authored by Artem Halushko
1 parent 60d8f79f

entity and map fixes

... ... @@ -450,47 +450,46 @@ export function aspectCache(imageUrl: string): Observable<number> {
450 450
451 451
452 452 export function parseArray(input: any[]): any[] {
453   - const alliases: any = _(input).groupBy(el => el?.datasource?.aliasName).values().value();
454   - return alliases.map((alliasArray, dsIndex) =>
455   - alliasArray[0].data.map((el, i) => {
  453 + return _(input).groupBy(el => el?.datasource?.entityName)
  454 + .values().value().map((entityArray, dsIndex) =>
  455 + entityArray[0].data.map((el, i) => {
  456 + const obj = {
  457 + entityName: entityArray[0]?.datasource?.entityName,
  458 + $datasource: entityArray[0]?.datasource,
  459 + dsIndex,
  460 + time: el[0],
  461 + deviceType: null
  462 + };
  463 + entityArray.forEach(entity => {
  464 + obj[entity?.dataKey?.label] = entity?.data[i][1];
  465 + obj[entity?.dataKey?.label + '|ts'] = entity?.data[0][0];
  466 + if (entity?.dataKey?.label === 'type') {
  467 + obj.deviceType = entity?.data[0][1];
  468 + }
  469 + });
  470 + return obj;
  471 + })
  472 + );
  473 +}
  474 +
  475 +export function parseData(input: any[]): any[] {
  476 + return _(input).groupBy(el => el?.datasource?.entityName)
  477 + .values().value().map((entityArray, i) => {
456 478 const obj = {
457   - aliasName: alliasArray[0]?.datasource?.aliasName,
458   - entityName: alliasArray[0]?.datasource?.entityName,
459   - $datasource: alliasArray[0]?.datasource,
460   - dsIndex,
461   - time: el[0],
  479 + entityName: entityArray[0]?.datasource?.entityName,
  480 + $datasource: entityArray[0]?.datasource,
  481 + dsIndex: i,
462 482 deviceType: null
463 483 };
464   - alliasArray.forEach(el => {
465   - obj[el?.dataKey?.label] = el?.data[i][1];
  484 + entityArray.forEach(el => {
  485 + obj[el?.dataKey?.label] = el?.data[0][1];
466 486 obj[el?.dataKey?.label + '|ts'] = el?.data[0][0];
467 487 if (el?.dataKey?.label === 'type') {
468 488 obj.deviceType = el?.data[0][1];
469 489 }
470 490 });
471 491 return obj;
472   - })
473   - );
474   -}
475   -
476   -export function parseData(input: any[]): any[] {
477   - return _(input).groupBy(el => el?.datasource?.aliasName).values().value().map((alliasArray, i) => {
478   - const obj = {
479   - aliasName: alliasArray[0]?.datasource?.aliasName,
480   - entityName: alliasArray[0]?.datasource?.entityName,
481   - $datasource: alliasArray[0]?.datasource,
482   - dsIndex: i,
483   - deviceType: null
484   - };
485   - alliasArray.forEach(el => {
486   - obj[el?.dataKey?.label] = el?.data[0][1];
487   - obj[el?.dataKey?.label + '|ts'] = el?.data[0][0];
488   - if (el?.dataKey?.label === 'type') {
489   - obj.deviceType = el?.data[0][1];
490   - }
491 492 });
492   - return obj;
493   - });
494 493 }
495 494
496 495 export function safeExecute(func: Function, params = []) {
... ...
... ... @@ -14,26 +14,27 @@
14 14 /// limitations under the License.
15 15 ///
16 16
17   -import L from 'leaflet';
  17 +import L, { LatLngTuple } from 'leaflet';
18 18
19 19 import 'leaflet-providers';
20 20 import 'leaflet.markercluster/dist/MarkerCluster.css'
21 21 import 'leaflet.markercluster/dist/MarkerCluster.Default.css'
22 22 import 'leaflet.markercluster/dist/leaflet.markercluster'
23 23
24   -import { MapSettings, MarkerSettings, FormattedData, UnitedMapSettings, PolygonSettings } from './map-models';
  24 +import { MapSettings, MarkerSettings, FormattedData, UnitedMapSettings, PolygonSettings, PolylineSettings } from './map-models';
25 25 import { Marker } from './markers';
26 26 import { Observable, of, BehaviorSubject, Subject } from 'rxjs';
27 27 import { filter } from 'rxjs/operators';
28 28 import { Polyline } from './polyline';
29 29 import { Polygon } from './polygon';
  30 +import { DatasourceData } from '@app/shared/models/widget.models';
30 31
31 32 export default abstract class LeafletMap {
32 33
33 34 markers: Map<string, Marker> = new Map();
  35 + polylines: Map<string, Polyline> = new Map();
  36 + polygons: Map<string, Polygon> = new Map();
34 37 dragMode = true;
35   - poly: Polyline;
36   - polygon: Polygon;
37 38 map: L.Map;
38 39 map$: BehaviorSubject<L.Map> = new BehaviorSubject(null);
39 40 ready$: Observable<L.Map> = this.map$.pipe(filter(map => !!map));
... ... @@ -78,15 +79,14 @@ export default abstract class LeafletMap {
78 79 const updatedEnttity = { ...ds, ...customLatLng };
79 80 this.saveMarkerLocation(updatedEnttity);
80 81 this.map.removeLayer(newMarker);
81   - this.deleteMarker(ds.aliasName);
82   - this.createMarker(ds.aliasName, updatedEnttity, this.datasources, this.options, false);
  82 + this.deleteMarker(ds.entityName);
  83 + this.createMarker(ds.entityName, updatedEnttity, this.datasources, this.options, false);
83 84 }
84 85 datasourcesList.append(dsItem);
85 86 })
86 87 const popup = L.popup();
87 88 popup.setContent(datasourcesList);
88 89 newMarker.bindPopup(popup).openPopup();
89   -
90 90 }
91 91 addMarker.setPosition('topright')
92 92 }
... ... @@ -165,6 +165,7 @@ export default abstract class LeafletMap {
165 165 }
166 166
167 167 convertPosition(expression: object): L.LatLng {
  168 + if (!expression) return null;
168 169 const lat = expression[this.options.latKeyName];
169 170 const lng = expression[this.options.lngKeyName];
170 171 if (isNaN(lat) || isNaN(lng))
... ... @@ -192,11 +193,11 @@ export default abstract class LeafletMap {
192 193 else {
193 194 this.options.icon = null;
194 195 }
195   - if (this.markers.get(data.aliasName)) {
196   - this.updateMarker(data.aliasName, data, markersData, this.options)
  196 + if (this.markers.get(data.entityName)) {
  197 + this.updateMarker(data.entityName, data, markersData, this.options)
197 198 }
198 199 else {
199   - this.createMarker(data.aliasName, data, markersData, this.options as MarkerSettings);
  200 + this.createMarker(data.entityName, data, markersData, this.options as MarkerSettings);
200 201 }
201 202 }
202 203 });
... ... @@ -207,16 +208,16 @@ export default abstract class LeafletMap {
207 208 this.saveMarkerLocation({ ...data, ...this.convertToCustomFormat(e.target._latlng) });
208 209 }
209 210
210   - private createMarker(key, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings, setFocus = true) {
  211 + private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings, setFocus = true) {
211 212 this.ready$.subscribe(() => {
212 213 const newMarker = new Marker(this.map, this.convertPosition(data), settings, data, dataSources, () => { }, this.dragMarker);
213   - if (setFocus && settings.fitMapBounds)
  214 + if (setFocus /*&& settings.fitMapBounds*/)
214 215 this.map.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng()).pad(0.2));
215 216 this.markers.set(key, newMarker);
216 217 });
217 218 }
218 219
219   - private updateMarker(key, data, dataSources, settings: MarkerSettings) {
  220 + private updateMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings) {
220 221 const marker: Marker = this.markers.get(key);
221 222 const location = this.convertPosition(data)
222 223 if (!location.equals(marker.location)) {
... ... @@ -229,7 +230,7 @@ export default abstract class LeafletMap {
229 230 marker.updateMarkerIcon(settings);
230 231 }
231 232
232   - deleteMarker(key) {
  233 + deleteMarker(key: string) {
233 234 let marker = this.markers.get(key)?.leafletMarker;
234 235 if (marker) {
235 236 this.map.removeLayer(marker);
... ... @@ -240,12 +241,12 @@ export default abstract class LeafletMap {
240 241
241 242 // Polyline
242 243
243   - updatePolylines(polyData: Array<Array<any>>) {
244   - polyData.forEach(data => {
  244 + updatePolylines(polyData: FormattedData[][]) {
  245 + polyData.forEach((data: FormattedData[]) => {
245 246 if (data.length) {
246 247 const dataSource = polyData.map(arr => arr[0]);
247   - if (this.poly) {
248   - this.updatePolyline(data, dataSource, this.options);
  248 + if (this.polylines.get(data[0].entityName)) {
  249 + this.updatePolyline(data[0].entityName, data, dataSource, this.options);
249 250 }
250 251 else {
251 252 this.createPolyline(data, dataSource, this.options);
... ... @@ -254,67 +255,59 @@ export default abstract class LeafletMap {
254 255 })
255 256 }
256 257
257   - createPolyline(data: any[], dataSources, settings) {
  258 + createPolyline(data: FormattedData[], dataSources: FormattedData[], settings: PolylineSettings) {
258 259 if (data.length)
259 260 this.ready$.subscribe(() => {
260   - this.poly = new Polyline(this.map,
  261 + const poly = new Polyline(this.map,
261 262 data.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings);
262   - const bounds = this.bounds.extend(this.poly.leafletPoly.getBounds().pad(0.2));
  263 + const bounds = this.bounds.extend(poly.leafletPoly.getBounds().pad(0.2));
263 264 if (bounds.isValid()) {
264 265 this.map.fitBounds(bounds);
265 266 this.bounds = bounds;
266 267 }
  268 + this.polylines.set(data[0].entityName, poly)
267 269 });
268 270 }
269 271
270   - updatePolyline(data, dataSources, settings) {
  272 + updatePolyline(key: string, data: FormattedData[], dataSources: FormattedData[], settings: PolylineSettings) {
271 273 this.ready$.subscribe(() => {
272   - this.poly.updatePolyline(settings, data, dataSources);
273   - const bounds = this.bounds.extend(this.poly.leafletPoly.getBounds().pad(0.2));
274   - if (bounds.isValid()) {
275   - this.map.fitBounds(bounds);
276   - this.bounds = bounds;
277   - }
  274 + this.polylines.get(key).updatePolyline(settings, data, dataSources);
278 275 });
279 276 }
280 277
281 278 // Polygon
282 279
283   - updatePolygons(polyData: any[]) {
284   - polyData.forEach((data: any) => {
  280 + updatePolygons(polyData: DatasourceData[]) {
  281 + polyData.forEach((data: DatasourceData) => {
285 282 if (data.data.length && data.dataKey.name === this.options.polygonKeyName) {
286 283 if (typeof (data?.data[0][1]) === 'string') {
287   - data.data = JSON.parse(data.data[0][1]);
  284 + data.data = JSON.parse(data.data[0][1]) as LatLngTuple[];
288 285 }
289   - if (this.polygon) {
290   - this.updatePolygon(data.data, polyData, this.options);
  286 + if (this.polygons.get(data.datasource.entityName)) {
  287 + this.updatePolygon(data.datasource.entityName, data.data, polyData, this.options);
291 288 }
292 289 else {
293   - this.createPolygon(data.data, polyData, this.options);
  290 + this.createPolygon(data.datasource.entityName, data.data, polyData, this.options);
294 291 }
295 292 }
296 293 });
297 294 }
298 295
299   - createPolygon(data: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) {
  296 + createPolygon(key: string, data: LatLngTuple[], dataSources: DatasourceData[], settings: PolygonSettings) {
300 297 this.ready$.subscribe(() => {
301   - this.polygon = new Polygon(this.map, data, dataSources, settings);
302   - const bounds = this.bounds.extend(this.polygon.leafletPoly.getBounds().pad(0.2));
  298 + const polygon = new Polygon(this.map, data, dataSources, settings);
  299 + const bounds = this.bounds.extend(polygon.leafletPoly.getBounds().pad(0.2));
303 300 if (bounds.isValid()) {
304 301 this.map.fitBounds(bounds);
305 302 this.bounds = bounds;
306 303 }
  304 + this.polygons.set(key, polygon);
307 305 });
308 306 }
309 307
310   - updatePolygon(data, dataSources, settings) {
  308 + updatePolygon(key: string, data: LatLngTuple[], dataSources: DatasourceData[], settings: PolygonSettings) {
311 309 this.ready$.subscribe(() => {
312   - // this.polygon.updatePolygon(settings, data, dataSources);
313   - const bounds = this.bounds.extend(this.polygon.leafletPoly.getBounds().pad(0.2));
314   - if (bounds.isValid()) {
315   - this.map.fitBounds(bounds);
316   - this.bounds = bounds;
317   - }
  310 + this.polygons.get(key).updatePolygon(data, dataSources, settings);
318 311 });
319 312 }
320 313 }
\ No newline at end of file
... ...
... ... @@ -131,4 +131,4 @@ export interface HistorySelectSettings {
131 131 buttonColor: string;
132 132 }
133 133
134   -export type UnitedMapSettings = MapSettings & PolygonSettings & MarkerSettings & PolygonSettings;
\ No newline at end of file
  134 +export type UnitedMapSettings = MapSettings & PolygonSettings & MarkerSettings & PolylineSettings;
\ No newline at end of file
... ...
... ... @@ -74,7 +74,8 @@ export class Marker {
74 74
75 75 if (settings.showLabel) {
76 76 if (settings.useLabelFunction) {
77   - settings.labelText = safeExecute(settings.labelFunction, [this.data, this.dataSources, this.data.dsIndex])
  77 + settings.labelText = parseTemplate(
  78 + safeExecute(settings.labelFunction, [this.data, this.dataSources, this.data.dsIndex]), this.data)
78 79 }
79 80 else settings.labelText = parseTemplate(settings.label, this.data);
80 81 this.leafletMarker.bindTooltip(`<div style="color: ${settings.labelColor};"><b>${settings.labelText}</b></div>`,
... ...
... ... @@ -14,14 +14,17 @@
14 14 /// limitations under the License.
15 15 ///
16 16
17   -import L, { LatLngExpression } from 'leaflet';
  17 +import L, { LatLngExpression, LatLngTuple } from 'leaflet';
18 18 import { createTooltip } from './maps-utils';
19 19 import { PolygonSettings } from './map-models';
  20 +import { DatasourceData } from '@app/shared/models/widget.models';
20 21
21 22 export class Polygon {
22 23
23 24 leafletPoly: L.Polygon;
24 25 tooltip;
  26 + data;
  27 + dataSources;
25 28
26 29 constructor(public map, coordinates, dataSources, settings: PolygonSettings, onClickListener?) {
27 30 this.leafletPoly = L.polygon(coordinates, {
... ... @@ -41,6 +44,13 @@ export class Polygon {
41 44 }
42 45 }
43 46
  47 + updatePolygon(data: LatLngTuple[], dataSources: DatasourceData[], settings: PolygonSettings) {
  48 + this.data = data;
  49 + this.dataSources = dataSources;
  50 + this.leafletPoly.setLatLngs(data);
  51 + this.updatePolygonColor(settings);
  52 + }
  53 +
44 54 removePolygon() {
45 55 this.map.removeLayer(this.leafletPoly);
46 56 }
... ...
... ... @@ -253,6 +253,11 @@ export const commonMapSettingsSchema =
253 253 type: 'boolean',
254 254 default: true
255 255 },
  256 + draggableMarker: {
  257 + title: 'Draggable Marker',
  258 + type: 'boolean',
  259 + default: false
  260 + },
256 261 disableScrollZooming: {
257 262 title: 'Disable scroll zooming',
258 263 type: 'boolean',
... ... @@ -371,11 +376,6 @@ export const commonMapSettingsSchema =
371 376 title: 'Polygon Color function: f(data, dsData, dsIndex)',
372 377 type: 'string'
373 378 },
374   - draggableMarker: {
375   - title: 'Draggable Marker',
376   - type: 'boolean',
377   - default: false
378   - },
379 379 markerImage: {
380 380 title: 'Custom marker image',
381 381 type: 'string'
... ... @@ -410,13 +410,13 @@ export const commonMapSettingsSchema =
410 410 'useDefaultCenterPosition',
411 411 'defaultCenterPosition',
412 412 'fitMapBounds',
  413 + 'draggableMarker',
413 414 'disableScrollZooming',
414 415 'latKeyName',
415 416 'lngKeyName',
416 417 'showLabel',
417 418 'label',
418 419 'useLabelFunction',
419   - 'draggableMarker',
420 420 {
421 421 key: 'labelFunction',
422 422 type: 'javascript'
... ...