Browse Source

Fix alarm data subscription. Maps cluster mode optimizations.

pull/3261/head
Igor Kulikov 6 years ago
parent
commit
02b6cf6de7
  1. 6
      ui-ngx/src/app/core/api/alarm-data-subscription.ts
  2. 2
      ui-ngx/src/app/core/api/alarm-data.service.ts
  3. 82
      ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts
  4. 5
      ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts
  5. 29
      ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts

6
ui-ngx/src/app/core/api/alarm-data-subscription.ts

@ -31,7 +31,6 @@ import {
} from '@shared/models/query/query.models'; } from '@shared/models/query/query.models';
import { SubscriptionTimewindow } from '@shared/models/time/time.models'; import { SubscriptionTimewindow } from '@shared/models/time/time.models';
import { AlarmDataListener } from '@core/api/alarm-data.service'; import { AlarmDataListener } from '@core/api/alarm-data.service';
import { UtilsService } from '@core/services/utils.service';
import { PageData } from '@shared/models/page/page-data'; import { PageData } from '@shared/models/page/page-data';
import { deepClone, isDefined, isDefinedAndNotNull, isObject } from '@core/utils'; import { deepClone, isDefined, isDefinedAndNotNull, isObject } from '@core/utils';
import { simulatedAlarm } from '@shared/models/alarm.models'; import { simulatedAlarm } from '@shared/models/alarm.models';
@ -68,8 +67,7 @@ export class AlarmDataSubscription {
constructor(public alarmDataSubscriptionOptions: AlarmDataSubscriptionOptions, constructor(public alarmDataSubscriptionOptions: AlarmDataSubscriptionOptions,
private listener: AlarmDataListener, private listener: AlarmDataListener,
private telemetryService: TelemetryService, private telemetryService: TelemetryService) {
private utils: UtilsService) {
} }
public unsubscribe() { public unsubscribe() {
@ -166,7 +164,7 @@ export class AlarmDataSubscription {
private onPageData(pageData: PageData<AlarmData>, allowedEntities: number, totalEntities: number) { private onPageData(pageData: PageData<AlarmData>, allowedEntities: number, totalEntities: number) {
this.pageData = pageData; this.pageData = pageData;
this.resetData(); this.resetData();
this.listener.alarmsLoaded(pageData, this.alarmDataSubscriptionOptions.pageLink, allowedEntities, totalEntities); this.listener.alarmsLoaded(pageData, allowedEntities, totalEntities);
} }
private onDataUpdate(update: Array<AlarmData>) { private onDataUpdate(update: Array<AlarmData>) {

2
ui-ngx/src/app/core/api/alarm-data.service.ts

@ -31,7 +31,7 @@ import { deepClone } from '@core/utils';
export interface AlarmDataListener { export interface AlarmDataListener {
subscriptionTimewindow?: SubscriptionTimewindow; subscriptionTimewindow?: SubscriptionTimewindow;
alarmSource: Datasource; alarmSource: Datasource;
alarmsLoaded: (pageData: PageData<AlarmData>, pageLink: AlarmDataPageLink, allowedEntities: number, totalEntities: number) => void; alarmsLoaded: (pageData: PageData<AlarmData>, allowedEntities: number, totalEntities: number) => void;
alarmsUpdated: (update: Array<AlarmData>, pageData: PageData<AlarmData>) => void; alarmsUpdated: (update: Array<AlarmData>, pageData: PageData<AlarmData>) => void;
subscription?: AlarmDataSubscription; subscription?: AlarmDataSubscription;
} }

82
ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts

@ -15,7 +15,7 @@
/// ///
import L, { import L, {
FeatureGroup, FeatureGroup, Icon,
LatLngBounds, LatLngBounds,
LatLngTuple, LatLngTuple,
markerClusterGroup, markerClusterGroup,
@ -59,6 +59,7 @@ export default abstract class LeafletMap {
points: FeatureGroup; points: FeatureGroup;
markersData: FormattedData[] = []; markersData: FormattedData[] = [];
polygonsData: FormattedData[] = []; polygonsData: FormattedData[] = [];
defaultMarkerIconInfo: { size: number[], icon: Icon };
protected constructor(public ctx: WidgetContext, protected constructor(public ctx: WidgetContext,
public $container: HTMLElement, public $container: HTMLElement,
@ -308,7 +309,11 @@ export default abstract class LeafletMap {
updateMarkers(markersData: FormattedData[], updateBounds = true, callback?) { updateMarkers(markersData: FormattedData[], updateBounds = true, callback?) {
const rawMarkers = markersData.filter(mdata => !!this.convertPosition(mdata)); const rawMarkers = markersData.filter(mdata => !!this.convertPosition(mdata));
this.ready$.subscribe(() => { this.ready$.subscribe(() => {
const keys: string[] = []; const toDelete = new Set(Array.from(this.markers.keys()));
const createdMarkers: Marker[] = [];
const updatedMarkers: Marker[] = [];
const deletedMarkers: Marker[] = [];
let m: Marker;
rawMarkers.forEach(data => { rawMarkers.forEach(data => {
if (data.rotationAngle || data.rotationAngle === 0) { if (data.rotationAngle || data.rotationAngle === 0) {
const currentImage = this.options.useMarkerImageFunction ? const currentImage = this.options.useMarkerImageFunction ?
@ -325,22 +330,36 @@ export default abstract class LeafletMap {
this.options.icon = null; this.options.icon = null;
} }
if (this.markers.get(data.entityName)) { if (this.markers.get(data.entityName)) {
this.updateMarker(data.entityName, data, markersData, this.options) m = this.updateMarker(data.entityName, data, markersData, this.options);
if (m) {
updatedMarkers.push(m);
}
} else { } else {
this.createMarker(data.entityName, data, markersData, this.options as MarkerSettings, updateBounds, callback); m = this.createMarker(data.entityName, data, markersData, this.options as MarkerSettings, updateBounds, callback);
} if (m) {
keys.push(data.entityName); createdMarkers.push(m);
}); }
const toDelete: string[] = [];
this.markers.forEach((v, mKey) => {
if (!keys.includes(mKey)) {
toDelete.push(mKey);
} }
toDelete.delete(data.entityName);
}); });
toDelete.forEach((key) => { toDelete.forEach((key) => {
this.deleteMarker(key); m = this.deleteMarker(key);
if (m) {
deletedMarkers.push(m);
}
}); });
this.markersData = markersData; this.markersData = markersData;
if ((this.options as MarkerSettings).useClusterMarkers) {
if (createdMarkers.length) {
this.markersCluster.addLayers(createdMarkers.map(marker => marker.leafletMarker));
}
if (updatedMarkers.length) {
this.markersCluster.refreshClusters(updatedMarkers.map(marker => marker.leafletMarker))
}
if (deletedMarkers.length) {
this.markersCluster.removeLayers(deletedMarkers.map(marker => marker.leafletMarker));
}
}
}); });
} }
@ -350,22 +369,20 @@ export default abstract class LeafletMap {
} }
private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings, private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings,
updateBounds = true, callback?) { updateBounds = true, callback?): Marker {
const newMarker = new Marker(this.convertPosition(data), settings, data, dataSources, this.dragMarker); const newMarker = new Marker(this, this.convertPosition(data), settings, data, dataSources, this.dragMarker);
if (callback) if (callback)
newMarker.leafletMarker.on('click', () => { callback(data, true) }); newMarker.leafletMarker.on('click', () => { callback(data, true) });
if (this.bounds && updateBounds) if (this.bounds && updateBounds)
this.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng())); this.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng()));
this.markers.set(key, newMarker); this.markers.set(key, newMarker);
if (this.options.useClusterMarkers) { if (!this.options.useClusterMarkers) {
this.markersCluster.addLayer(newMarker.leafletMarker); this.map.addLayer(newMarker.leafletMarker);
}
else {
this.map.addLayer(newMarker.leafletMarker);
} }
return newMarker;
} }
private updateMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings) { private updateMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings): Marker {
const marker: Marker = this.markers.get(key); const marker: Marker = this.markers.get(key);
const location = this.convertPosition(data) const location = this.convertPosition(data)
if (!location.equals(marker.location)) { if (!location.equals(marker.location)) {
@ -374,24 +391,21 @@ export default abstract class LeafletMap {
if (settings.showTooltip) { if (settings.showTooltip) {
marker.updateMarkerTooltip(data); marker.updateMarkerTooltip(data);
} }
if (settings.useClusterMarkers) {
this.markersCluster.refreshClusters()
}
marker.setDataSources(data, dataSources); marker.setDataSources(data, dataSources);
marker.updateMarkerIcon(settings); marker.updateMarkerIcon(settings);
return marker;
} }
deleteMarker(key: string) { deleteMarker(key: string): Marker {
let marker = this.markers.get(key)?.leafletMarker; const marker = this.markers.get(key);
if (marker) { const leafletMarker = marker?.leafletMarker;
if (this.options.useClusterMarkers) { if (leafletMarker) {
this.markersCluster.removeLayer(marker); if (!this.options.useClusterMarkers) {
} else { this.map.removeLayer(leafletMarker);
this.map.removeLayer(marker); }
} this.markers.delete(key);
this.markers.delete(key); }
marker = null; return marker;
}
} }
updatePoints(pointsData: FormattedData[], getTooltip: (point: FormattedData, setTooltip?: boolean) => string) { updatePoints(pointsData: FormattedData[], getTooltip: (point: FormattedData, setTooltip?: boolean) => string) {

5
ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts

@ -210,8 +210,9 @@ function parseTemplate(template: string, data: { $datasource?: Datasource, [key:
match = buttonActionRegex.exec(template); match = buttonActionRegex.exec(template);
} }
const compiled = _.template(template); // const compiled = _.template(template);
res = compiled(data); // res = compiled(data);
res = template;
} catch (ex) { } catch (ex) {
console.log(ex, template) console.log(ex, template)
} }

29
ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts

@ -19,6 +19,7 @@ import { FormattedData, MarkerSettings } from './map-models';
import { aspectCache, bindPopupActions, createTooltip, parseWithTranslation, safeExecute } from './maps-utils'; import { aspectCache, bindPopupActions, createTooltip, parseWithTranslation, safeExecute } from './maps-utils';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { isDefined } from '@core/utils'; import { isDefined } from '@core/utils';
import LeafletMap from './leaflet-map';
export class Marker { export class Marker {
leafletMarker: L.Marker; leafletMarker: L.Marker;
@ -29,7 +30,7 @@ export class Marker {
data: FormattedData; data: FormattedData;
dataSources: FormattedData[]; dataSources: FormattedData[];
constructor(location: L.LatLngExpression, public settings: MarkerSettings, constructor(private map: LeafletMap, location: L.LatLngExpression, public settings: MarkerSettings,
data?: FormattedData, dataSources?, onDragendListener?) { data?: FormattedData, dataSources?, onDragendListener?) {
this.setDataSources(data, dataSources); this.setDataSources(data, dataSources);
this.leafletMarker = L.marker(location, { this.leafletMarker = L.marker(location, {
@ -158,24 +159,24 @@ export class Marker {
} }
createDefaultMarkerIcon(color, onMarkerIconReady) { createDefaultMarkerIcon(color, onMarkerIconReady) {
if (!this.map.defaultMarkerIconInfo) {
const icon = L.icon({ const icon = L.icon({
iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + color, iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + color,
iconSize: [21, 34], iconSize: [21, 34],
iconAnchor: [21 * this.markerOffset[0], 34 * this.markerOffset[1]], iconAnchor: [21 * this.markerOffset[0], 34 * this.markerOffset[1]],
popupAnchor: [0, -34], popupAnchor: [0, -34],
shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow', shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow',
shadowSize: [40, 37], shadowSize: [40, 37],
shadowAnchor: [12, 35] shadowAnchor: [12, 35]
}); });
const iconInfo = { this.map.defaultMarkerIconInfo = {
size: [21, 34], size: [21, 34],
icon icon
}; };
onMarkerIconReady(iconInfo); }
onMarkerIconReady(this.map.defaultMarkerIconInfo);
} }
removeMarker() { removeMarker() {
/* this.map$.subscribe(map => /* this.map$.subscribe(map =>
this.leafletMarker.addTo(map))*/ this.leafletMarker.addTo(map))*/

Loading…
Cancel
Save