Commit b86c5e61e1168e5cfa49eaf9350aa211c7b409b4
1 parent
0206a8ab
Image map fixes and improvements. Fixed state chart subscription.
Showing
9 changed files
with
122 additions
and
89 deletions
... | ... | @@ -314,7 +314,7 @@ export class DatasourceSubscription { |
314 | 314 | }); |
315 | 315 | stateDataReceived = true; |
316 | 316 | } else { |
317 | - firstStateData = data; | |
317 | + firstStateData = subscriptionUpdate; | |
318 | 318 | } |
319 | 319 | } else { |
320 | 320 | if (subsTw.aggregation.stateData && !stateDataReceived) { | ... | ... |
... | ... | @@ -33,6 +33,7 @@ import { filter } from 'rxjs/operators'; |
33 | 33 | import { Polyline } from './polyline'; |
34 | 34 | import { Polygon } from './polygon'; |
35 | 35 | import { createTooltip, safeExecute } from '@home/components/widget/lib/maps/maps-utils'; |
36 | +import { WidgetContext } from '@home/models/widget-component.models'; | |
36 | 37 | |
37 | 38 | export default abstract class LeafletMap { |
38 | 39 | |
... | ... | @@ -49,7 +50,9 @@ export default abstract class LeafletMap { |
49 | 50 | points: FeatureGroup; |
50 | 51 | markersData: FormattedData[] = []; |
51 | 52 | |
52 | - protected constructor(public $container: HTMLElement, options: UnitedMapSettings) { | |
53 | + protected constructor(public ctx: WidgetContext, | |
54 | + public $container: HTMLElement, | |
55 | + options: UnitedMapSettings) { | |
53 | 56 | this.options = options; |
54 | 57 | } |
55 | 58 | |
... | ... | @@ -341,9 +344,6 @@ export default abstract class LeafletMap { |
341 | 344 | }); |
342 | 345 | } |
343 | 346 | |
344 | - setImageAlias(alias: Observable<any>) { | |
345 | - } | |
346 | - | |
347 | 347 | // Polyline |
348 | 348 | |
349 | 349 | updatePolylines(polyData: FormattedData[][], data?: FormattedData) { | ... | ... |
... | ... | @@ -165,6 +165,12 @@ export interface HistorySelectSettings { |
165 | 165 | buttonColor: string; |
166 | 166 | } |
167 | 167 | |
168 | +export interface MapImage { | |
169 | + imageUrl: string; | |
170 | + aspect: number; | |
171 | + update?: boolean; | |
172 | +} | |
173 | + | |
168 | 174 | export type TripAnimationSettings = { |
169 | 175 | showPoints: boolean; |
170 | 176 | pointColor: string; | ... | ... |
... | ... | @@ -17,26 +17,18 @@ |
17 | 17 | import { defaultSettings, hereProviders, MapProviders, providerSets, UnitedMapSettings } from './map-models'; |
18 | 18 | import LeafletMap from './leaflet-map'; |
19 | 19 | import { |
20 | - commonMapSettingsSchema, | |
21 | - mapPolygonSchema, | |
22 | - mapProviderSchema, | |
23 | - markerClusteringSettingsSchema, | |
24 | - markerClusteringSettingsSchemaLeaflet, | |
25 | - routeMapSettingsSchema | |
20 | + commonMapSettingsSchema, | |
21 | + mapPolygonSchema, | |
22 | + mapProviderSchema, | |
23 | + markerClusteringSettingsSchema, | |
24 | + markerClusteringSettingsSchemaLeaflet, | |
25 | + routeMapSettingsSchema | |
26 | 26 | } from './schemes'; |
27 | 27 | import { MapWidgetInterface, MapWidgetStaticInterface } from './map-widget.interface'; |
28 | 28 | import { addCondition, addGroupInfo, addToSchema, initSchema, mergeSchemes } from '@core/schema-utils'; |
29 | -import { of, Subject } from 'rxjs'; | |
30 | 29 | import { WidgetContext } from '@app/modules/home/models/widget-component.models'; |
31 | 30 | import { getDefCenterPosition, parseArray, parseData, parseFunction, parseWithTranslation } from './maps-utils'; |
32 | -import { | |
33 | - Datasource, | |
34 | - DatasourceType, | |
35 | - JsonSettingsSchema, | |
36 | - WidgetActionDescriptor, | |
37 | - widgetType, | |
38 | - DatasourceData | |
39 | -} from '@shared/models/widget.models'; | |
31 | +import { Datasource, DatasourceData, JsonSettingsSchema, WidgetActionDescriptor } from '@shared/models/widget.models'; | |
40 | 32 | import { EntityId } from '@shared/models/id/entity-id'; |
41 | 33 | import { AttributeScope, DataKeyType, LatestTelemetry } from '@shared/models/telemetry/telemetry.models'; |
42 | 34 | import { AttributeService } from '@core/http/attribute.service'; |
... | ... | @@ -76,8 +68,7 @@ export class MapWidgetController implements MapWidgetInterface { |
76 | 68 | return; |
77 | 69 | } |
78 | 70 | parseWithTranslation.setTranslate(this.translate); |
79 | - this.map = new MapClass($element, this.settings, this.ctx.$injector); | |
80 | - this.map.setImageAlias(this.subscribeForImageAttribute()); | |
71 | + this.map = new MapClass(this.ctx, $element, this.settings, this.ctx.$injector); | |
81 | 72 | this.map.saveMarkerLocation = this.setMarkerLocation; |
82 | 73 | if (this.settings.draggableMarker) { |
83 | 74 | this.map.setDataSources(parseData(this.data)); |
... | ... | @@ -263,48 +254,6 @@ export class MapWidgetController implements MapWidgetInterface { |
263 | 254 | this.map.onResize(); |
264 | 255 | } |
265 | 256 | |
266 | - subscribeForImageAttribute() { | |
267 | - const imageEntityAlias = this.settings.imageEntityAlias; | |
268 | - const imageUrlAttribute = this.settings.imageUrlAttribute; | |
269 | - if (!imageEntityAlias || !imageUrlAttribute) { | |
270 | - return of(false); | |
271 | - } | |
272 | - const entityAliasId = this.ctx.aliasController.getEntityAliasId(imageEntityAlias); | |
273 | - if (!entityAliasId) { | |
274 | - return of(false); | |
275 | - } | |
276 | - const datasources = [ | |
277 | - { | |
278 | - type: DatasourceType.entity, | |
279 | - name: imageEntityAlias, | |
280 | - aliasName: imageEntityAlias, | |
281 | - entityAliasId, | |
282 | - dataKeys: [ | |
283 | - { | |
284 | - type: DataKeyType.attribute, | |
285 | - name: imageUrlAttribute, | |
286 | - label: imageUrlAttribute, | |
287 | - settings: {}, | |
288 | - _hash: Math.random() | |
289 | - } | |
290 | - ] | |
291 | - } | |
292 | - ]; | |
293 | - const result = new Subject(); | |
294 | - const imageUrlSubscriptionOptions = { | |
295 | - datasources, | |
296 | - useDashboardTimewindow: false, | |
297 | - type: widgetType.latest, | |
298 | - callbacks: { | |
299 | - onDataUpdated: (subscription) => { | |
300 | - result.next(subscription?.data[0]?.data[0]); | |
301 | - } | |
302 | - } | |
303 | - }; | |
304 | - this.ctx.subscriptionApi.createSubscription(imageUrlSubscriptionOptions, true).subscribe(() => { }); | |
305 | - return result; | |
306 | - } | |
307 | - | |
308 | 257 | onDestroy() { |
309 | 258 | } |
310 | 259 | } | ... | ... |
... | ... | @@ -21,6 +21,7 @@ import { UnitedMapSettings } from '../map-models'; |
21 | 21 | import 'leaflet.gridlayer.googlemutant'; |
22 | 22 | import { ResourcesService } from '@core/services/resources.service'; |
23 | 23 | import { Injector } from '@angular/core'; |
24 | +import { WidgetContext } from '@home/models/widget-component.models'; | |
24 | 25 | |
25 | 26 | const gmGlobals: GmGlobal = {}; |
26 | 27 | |
... | ... | @@ -31,8 +32,8 @@ interface GmGlobal { |
31 | 32 | export class GoogleMap extends LeafletMap { |
32 | 33 | private resource: ResourcesService; |
33 | 34 | |
34 | - constructor($container, options: UnitedMapSettings, private injector: Injector) { | |
35 | - super($container, options); | |
35 | + constructor(ctx: WidgetContext, $container, options: UnitedMapSettings, private injector: Injector) { | |
36 | + super(ctx, $container, options); | |
36 | 37 | this.resource = injector.get(ResourcesService); |
37 | 38 | this.loadGoogle(() => { |
38 | 39 | const map = L.map($container, {attributionControl: false}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); | ... | ... |
... | ... | @@ -17,10 +17,11 @@ |
17 | 17 | import L from 'leaflet'; |
18 | 18 | import LeafletMap from '../leaflet-map'; |
19 | 19 | import { UnitedMapSettings } from '../map-models'; |
20 | +import { WidgetContext } from '@home/models/widget-component.models'; | |
20 | 21 | |
21 | 22 | export class HEREMap extends LeafletMap { |
22 | - constructor($container, options: UnitedMapSettings) { | |
23 | - super($container, options); | |
23 | + constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) { | |
24 | + super(ctx, $container, options); | |
24 | 25 | const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); |
25 | 26 | const tileLayer = (L.tileLayer as any).provider(options.mapProviderHere || 'HERE.normalDay', options.credentials); |
26 | 27 | tileLayer.addTo(map); | ... | ... |
... | ... | @@ -14,12 +14,16 @@ |
14 | 14 | /// limitations under the License. |
15 | 15 | /// |
16 | 16 | |
17 | -import L, { LatLngLiteral, LatLngBounds, LatLngTuple } from 'leaflet'; | |
17 | +import L, { LatLngBounds, LatLngLiteral, LatLngTuple } from 'leaflet'; | |
18 | 18 | import LeafletMap from '../leaflet-map'; |
19 | -import { UnitedMapSettings, PosFuncton } from '../map-models'; | |
20 | -import { Observable } from 'rxjs'; | |
21 | -import { map, filter, switchMap } from 'rxjs/operators'; | |
19 | +import { MapImage, PosFuncton, UnitedMapSettings } from '../map-models'; | |
20 | +import { Observable, ReplaySubject } from 'rxjs'; | |
21 | +import { filter, map, mergeMap } from 'rxjs/operators'; | |
22 | 22 | import { aspectCache, calculateNewPointCoordinate, parseFunction } from '@home/components/widget/lib/maps/maps-utils'; |
23 | +import { WidgetContext } from '@home/models/widget-component.models'; | |
24 | +import { DataSet, DatasourceType, widgetType } from '@shared/models/widget.models'; | |
25 | +import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; | |
26 | +import { WidgetSubscriptionOptions } from '@core/api/widget-api.models'; | |
23 | 27 | |
24 | 28 | const maxZoom = 4;// ? |
25 | 29 | |
... | ... | @@ -32,26 +36,96 @@ export class ImageMap extends LeafletMap { |
32 | 36 | imageUrl: string; |
33 | 37 | posFunction: PosFuncton; |
34 | 38 | |
35 | - constructor($container: HTMLElement, options: UnitedMapSettings) { | |
36 | - super($container, options); | |
39 | + constructor(ctx: WidgetContext, $container: HTMLElement, options: UnitedMapSettings) { | |
40 | + super(ctx, $container, options); | |
37 | 41 | this.posFunction = parseFunction(options.posFunction, ['origXPos', 'origYPos']) as PosFuncton; |
38 | - this.imageUrl = options.mapUrl; | |
39 | - aspectCache(this.imageUrl).subscribe(aspect => { | |
40 | - this.aspect = aspect; | |
42 | + this.mapImage(options).subscribe((mapImage) => { | |
43 | + this.imageUrl = mapImage.imageUrl; | |
44 | + this.aspect = mapImage.aspect; | |
45 | + if (mapImage.update) { | |
46 | + this.onResize(true); | |
47 | + } else { | |
41 | 48 | this.onResize(); |
42 | 49 | super.setMap(this.map); |
43 | 50 | super.initSettings(options); |
51 | + } | |
44 | 52 | }); |
45 | 53 | } |
46 | 54 | |
47 | - setImageAlias(alias: Observable<any>) { | |
48 | - alias.pipe(filter(result => result), map(el => el[1]), switchMap(res => { | |
49 | - this.imageUrl = res; | |
50 | - return aspectCache(res); | |
51 | - })).subscribe(aspect => { | |
52 | - this.aspect = aspect; | |
53 | - this.onResize(true); | |
54 | - }); | |
55 | + private mapImage(options: UnitedMapSettings): Observable<MapImage> { | |
56 | + const imageEntityAlias = options.imageEntityAlias; | |
57 | + const imageUrlAttribute = options.imageUrlAttribute; | |
58 | + if (!imageEntityAlias || !imageUrlAttribute) { | |
59 | + return this.imageFromUrl(options.mapUrl); | |
60 | + } | |
61 | + const entityAliasId = this.ctx.aliasController.getEntityAliasId(imageEntityAlias); | |
62 | + if (!entityAliasId) { | |
63 | + return this.imageFromUrl(options.mapUrl); | |
64 | + } | |
65 | + const datasources = [ | |
66 | + { | |
67 | + type: DatasourceType.entity, | |
68 | + name: imageEntityAlias, | |
69 | + aliasName: imageEntityAlias, | |
70 | + entityAliasId, | |
71 | + dataKeys: [ | |
72 | + { | |
73 | + type: DataKeyType.attribute, | |
74 | + name: imageUrlAttribute, | |
75 | + label: imageUrlAttribute, | |
76 | + settings: {}, | |
77 | + _hash: Math.random() | |
78 | + } | |
79 | + ] | |
80 | + } | |
81 | + ]; | |
82 | + const result = new ReplaySubject<[DataSet, boolean]>(); | |
83 | + let isUpdate = false; | |
84 | + const imageUrlSubscriptionOptions: WidgetSubscriptionOptions = { | |
85 | + datasources, | |
86 | + useDashboardTimewindow: false, | |
87 | + type: widgetType.latest, | |
88 | + callbacks: { | |
89 | + onDataUpdated: (subscription) => { | |
90 | + result.next([subscription.data[0]?.data, isUpdate]); | |
91 | + isUpdate = true; | |
92 | + } | |
93 | + } | |
94 | + }; | |
95 | + this.ctx.subscriptionApi.createSubscription(imageUrlSubscriptionOptions, true).subscribe(() => { }); | |
96 | + return this.imageFromAlias(result); | |
97 | + } | |
98 | + | |
99 | + private imageFromUrl(url: string): Observable<MapImage> { | |
100 | + return aspectCache(url).pipe( | |
101 | + map( aspect => { | |
102 | + const mapImage: MapImage = { | |
103 | + imageUrl: url, | |
104 | + aspect, | |
105 | + update: false | |
106 | + }; | |
107 | + return mapImage; | |
108 | + } | |
109 | + )); | |
110 | + } | |
111 | + | |
112 | + private imageFromAlias(alias: Observable<[DataSet, boolean]>): Observable<MapImage> { | |
113 | + return alias.pipe( | |
114 | + filter(result => result[0].length > 0), | |
115 | + mergeMap(res => { | |
116 | + const mapImage: MapImage = { | |
117 | + imageUrl: res[0][0][1], | |
118 | + aspect: null, | |
119 | + update: res[1] | |
120 | + }; | |
121 | + return aspectCache(mapImage.imageUrl).pipe( | |
122 | + map((aspect) => { | |
123 | + mapImage.aspect = aspect; | |
124 | + return mapImage; | |
125 | + } | |
126 | + )); | |
127 | + }) | |
128 | + ); | |
55 | 129 | } |
56 | 130 | |
57 | 131 | updateBounds(updateImage?: boolean, lastCenterPos?) { | ... | ... |
... | ... | @@ -17,10 +17,11 @@ |
17 | 17 | import L from 'leaflet'; |
18 | 18 | import LeafletMap from '../leaflet-map'; |
19 | 19 | import { UnitedMapSettings } from '../map-models'; |
20 | +import { WidgetContext } from '@home/models/widget-component.models'; | |
20 | 21 | |
21 | 22 | export class OpenStreetMap extends LeafletMap { |
22 | - constructor($container, options: UnitedMapSettings) { | |
23 | - super($container, options); | |
23 | + constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) { | |
24 | + super(ctx, $container, options); | |
24 | 25 | const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); |
25 | 26 | let tileLayer; |
26 | 27 | if (options.useCustomProvider) | ... | ... |
... | ... | @@ -18,10 +18,11 @@ |
18 | 18 | import L from 'leaflet'; |
19 | 19 | import LeafletMap from '../leaflet-map'; |
20 | 20 | import { UnitedMapSettings } from '../map-models'; |
21 | +import { WidgetContext } from '@home/models/widget-component.models'; | |
21 | 22 | |
22 | 23 | export class TencentMap extends LeafletMap { |
23 | - constructor($container, options: UnitedMapSettings) { | |
24 | - super($container, options); | |
24 | + constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) { | |
25 | + super(ctx, $container, options); | |
25 | 26 | const txUrl = 'http://rt{s}.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0'; |
26 | 27 | const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); |
27 | 28 | const txLayer = L.tileLayer(txUrl, { | ... | ... |