Showing
5 changed files
with
73 additions
and
44 deletions
... | ... | @@ -23,6 +23,7 @@ import { |
23 | 23 | EntityFilter, |
24 | 24 | EntityKey, |
25 | 25 | EntityKeyType, |
26 | + entityKeyTypeToDataKeyType, | |
26 | 27 | KeyFilter, |
27 | 28 | TsValue |
28 | 29 | } from '@shared/models/query/query.models'; |
... | ... | @@ -41,8 +42,8 @@ import { PageData } from '@shared/models/page/page-data'; |
41 | 42 | import { DataAggregator } from '@core/api/data-aggregator'; |
42 | 43 | import { NULL_UUID } from '@shared/models/id/has-uuid'; |
43 | 44 | import { EntityType } from '@shared/models/entity-type.models'; |
44 | -import Timeout = NodeJS.Timeout; | |
45 | 45 | import { Observable, of, ReplaySubject, Subject } from 'rxjs'; |
46 | +import Timeout = NodeJS.Timeout; | |
46 | 47 | |
47 | 48 | export interface EntityDataSubscriptionOptions { |
48 | 49 | datasourceType: DatasourceType; |
... | ... | @@ -473,7 +474,8 @@ export class EntityDataSubscription { |
473 | 474 | if (this.entityDataSubscriptionOptions.type === widgetType.latest && entityData.latest) { |
474 | 475 | for (const type of Object.keys(entityData.latest)) { |
475 | 476 | const subscriptionData = this.toSubscriptionData(entityData.latest[type], false); |
476 | - this.onData(subscriptionData, type, dataIndex, true, dataUpdatedCb); | |
477 | + const dataKeyType = entityKeyTypeToDataKeyType(EntityKeyType[type]); | |
478 | + this.onData(subscriptionData, dataKeyType, dataIndex, true, dataUpdatedCb); | |
477 | 479 | } |
478 | 480 | } |
479 | 481 | if (this.entityDataSubscriptionOptions.type === widgetType.timeseries && entityData.timeseries) { |
... | ... | @@ -486,7 +488,7 @@ export class EntityDataSubscription { |
486 | 488 | } |
487 | 489 | } |
488 | 490 | |
489 | - private onData(sourceData: SubscriptionData, type: string, dataIndex: number, detectChanges: boolean, | |
491 | + private onData(sourceData: SubscriptionData, type: DataKeyType, dataIndex: number, detectChanges: boolean, | |
490 | 492 | dataUpdatedCb: DataUpdatedCb) { |
491 | 493 | for (const keyName of Object.keys(sourceData)) { |
492 | 494 | const keyData = sourceData[keyName]; | ... | ... |
... | ... | @@ -52,7 +52,13 @@ import { EntityId } from '@app/shared/models/id/entity-id'; |
52 | 52 | import * as moment_ from 'moment'; |
53 | 53 | import { PageData } from '@shared/models/page/page-data'; |
54 | 54 | import { EntityDataListener } from '@core/api/entity-data.service'; |
55 | -import { EntityData, EntityDataPageLink, EntityKeyType, KeyFilter } from '@shared/models/query/query.models'; | |
55 | +import { | |
56 | + EntityData, | |
57 | + EntityDataPageLink, | |
58 | + entityDataToEntityInfo, | |
59 | + EntityKeyType, | |
60 | + KeyFilter | |
61 | +} from '@shared/models/query/query.models'; | |
56 | 62 | import { map } from 'rxjs/operators'; |
57 | 63 | |
58 | 64 | const moment = moment_; |
... | ... | @@ -414,6 +420,7 @@ export class WidgetSubscription implements IWidgetSubscription { |
414 | 420 | this.configureLoadedData(); |
415 | 421 | this.hasResolvedData = true; |
416 | 422 | this.notifyDataLoaded(); |
423 | + this.onDataUpdated(true); | |
417 | 424 | }) |
418 | 425 | ); |
419 | 426 | } |
... | ... | @@ -881,7 +888,6 @@ export class WidgetSubscription implements IWidgetSubscription { |
881 | 888 | |
882 | 889 | private dataSubscribe() { |
883 | 890 | if (!this.hasDataPageLink) { |
884 | - this.notifyDataLoading(); | |
885 | 891 | if (this.type === widgetType.timeseries && this.timeWindowConfig) { |
886 | 892 | this.updateRealtimeSubscription(); |
887 | 893 | if (this.comparisonEnabled) { |
... | ... | @@ -897,7 +903,6 @@ export class WidgetSubscription implements IWidgetSubscription { |
897 | 903 | this.ctx.entityDataService.startSubscription(listener); |
898 | 904 | }); |
899 | 905 | if (forceUpdate) { |
900 | - this.notifyDataLoaded(); | |
901 | 906 | this.onDataUpdated(); |
902 | 907 | } |
903 | 908 | } |
... | ... | @@ -1269,23 +1274,11 @@ export class WidgetSubscription implements IWidgetSubscription { |
1269 | 1274 | newDatasource.entityId = entityData.entityId.id; |
1270 | 1275 | newDatasource.entityType = entityData.entityId.entityType as EntityType; |
1271 | 1276 | if (configDatasource.type === DatasourceType.entity) { |
1272 | - let name; | |
1273 | - let label; | |
1274 | - if (entityData.latest && entityData.latest[EntityKeyType.ENTITY_FIELD]) { | |
1275 | - const fields = entityData.latest[EntityKeyType.ENTITY_FIELD]; | |
1276 | - if (fields.name) { | |
1277 | - name = fields.name.value; | |
1278 | - } | |
1279 | - if (fields.label) { | |
1280 | - label = fields.label.value; | |
1281 | - } | |
1282 | - } | |
1283 | - name = name || 'TODO'; | |
1284 | - label = label || 'TODO'; | |
1285 | - newDatasource.name = name; | |
1286 | - newDatasource.entityName = name; | |
1287 | - newDatasource.entityLabel = label; | |
1288 | - newDatasource.entityDescription = 'TODO'; | |
1277 | + const entityInfo = entityDataToEntityInfo(entityData); | |
1278 | + newDatasource.name = entityInfo.name; | |
1279 | + newDatasource.entityName = entityInfo.name; | |
1280 | + newDatasource.entityLabel = entityInfo.label; | |
1281 | + newDatasource.entityDescription = entityInfo.entityDescription; | |
1289 | 1282 | } |
1290 | 1283 | newDatasource.generated = index > 0 ? true : false; |
1291 | 1284 | return newDatasource; |
... | ... | @@ -1296,7 +1289,6 @@ export class WidgetSubscription implements IWidgetSubscription { |
1296 | 1289 | const startIndex = configuredDatasource.dataKeyStartIndex; |
1297 | 1290 | const dataKeysCount = configuredDatasource.dataKeys.length; |
1298 | 1291 | const index = startIndex + dataIndex*dataKeysCount + dataKeyIndex; |
1299 | - this.notifyDataLoaded(); | |
1300 | 1292 | let update = true; |
1301 | 1293 | let currentData: DataSetHolder; |
1302 | 1294 | if (this.displayLegend && this.legendData.keys[index].dataKey.hidden) { | ... | ... |
... | ... | @@ -54,7 +54,7 @@ import { AttributeService } from '@core/http/attribute.service'; |
54 | 54 | import { |
55 | 55 | createDefaultEntityDataPageLink, |
56 | 56 | EntityData, |
57 | - EntityDataQuery, | |
57 | + EntityDataQuery, entityDataToEntityInfo, | |
58 | 58 | EntityFilter, |
59 | 59 | EntityKeyType |
60 | 60 | } from '@shared/models/query/query.models'; |
... | ... | @@ -365,23 +365,6 @@ export class EntityService { |
365 | 365 | return this.http.post<PageData<EntityData>>('/api/entitiesQuery/find', query, defaultHttpOptionsFromConfig(config)); |
366 | 366 | } |
367 | 367 | |
368 | - private entityDataToEntityInfo(entityData: EntityData): EntityInfo { | |
369 | - const entityInfo: EntityInfo = { | |
370 | - id: entityData.entityId.id, | |
371 | - entityType: entityData.entityId.entityType as EntityType | |
372 | - }; | |
373 | - if (entityData.latest && entityData.latest[EntityKeyType.ENTITY_FIELD]) { | |
374 | - const fields = entityData.latest[EntityKeyType.ENTITY_FIELD]; | |
375 | - if (fields.name) { | |
376 | - entityInfo.name = fields.name.value; | |
377 | - } | |
378 | - if (fields.label) { | |
379 | - entityInfo.label = fields.label.value; | |
380 | - } | |
381 | - } | |
382 | - return entityInfo; | |
383 | - } | |
384 | - | |
385 | 368 | public findSingleEntityInfoByEntityFilter(filter: EntityFilter, config?: RequestConfig): Observable<EntityInfo> { |
386 | 369 | const query: EntityDataQuery = { |
387 | 370 | entityFilter: filter, |
... | ... | @@ -401,7 +384,7 @@ export class EntityService { |
401 | 384 | map((data) => { |
402 | 385 | if (data.data.length) { |
403 | 386 | const entityData = data.data[0]; |
404 | - return this.entityDataToEntityInfo(entityData); | |
387 | + return entityDataToEntityInfo(entityData); | |
405 | 388 | } else { |
406 | 389 | return null; |
407 | 390 | } | ... | ... |
... | ... | @@ -138,6 +138,8 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI |
138 | 138 | subscriptionInited = false; |
139 | 139 | destroyed = false; |
140 | 140 | widgetSizeDetected = false; |
141 | + widgetInstanceInited = false; | |
142 | + dataUpdatePending = false; | |
141 | 143 | |
142 | 144 | cafs: {[cafId: string]: CancelAnimationFrame} = {}; |
143 | 145 | |
... | ... | @@ -363,6 +365,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI |
363 | 365 | subscription.destroy(); |
364 | 366 | } |
365 | 367 | this.subscriptionInited = false; |
368 | + this.dataUpdatePending = false; | |
366 | 369 | this.widgetContext.subscriptions = {}; |
367 | 370 | if (this.widgetContext.inited) { |
368 | 371 | this.widgetContext.inited = false; |
... | ... | @@ -375,6 +378,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI |
375 | 378 | try { |
376 | 379 | if (shouldDestroyWidgetInstance) { |
377 | 380 | this.widgetTypeInstance.onDestroy(); |
381 | + this.widgetInstanceInited = false; | |
378 | 382 | } |
379 | 383 | } catch (e) { |
380 | 384 | this.handleWidgetException(e); |
... | ... | @@ -479,6 +483,11 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI |
479 | 483 | try { |
480 | 484 | if (this.displayWidgetInstance()) { |
481 | 485 | this.widgetTypeInstance.onInit(); |
486 | + this.widgetInstanceInited = true; | |
487 | + if (this.dataUpdatePending) { | |
488 | + this.widgetTypeInstance.onDataUpdated(); | |
489 | + this.dataUpdatePending = false; | |
490 | + } | |
482 | 491 | } else { |
483 | 492 | this.loadingData = false; |
484 | 493 | } |
... | ... | @@ -798,7 +807,11 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI |
798 | 807 | onDataUpdated: () => { |
799 | 808 | try { |
800 | 809 | if (this.displayWidgetInstance()) { |
801 | - this.widgetTypeInstance.onDataUpdated(); | |
810 | + if (this.widgetInstanceInited) { | |
811 | + this.widgetTypeInstance.onDataUpdated(); | |
812 | + } else { | |
813 | + this.dataUpdatePending = true; | |
814 | + } | |
802 | 815 | } |
803 | 816 | } catch (e){} |
804 | 817 | }, | ... | ... |
... | ... | @@ -17,6 +17,9 @@ |
17 | 17 | import { AliasFilterType, EntityFilters } from '@shared/models/alias.models'; |
18 | 18 | import { EntityId } from '@shared/models/id/entity-id'; |
19 | 19 | import { SortDirection } from '@angular/material/sort'; |
20 | +import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; | |
21 | +import { EntityInfo } from '@shared/models/entity.models'; | |
22 | +import { EntityType } from '@shared/models/entity-type.models'; | |
20 | 23 | |
21 | 24 | export enum EntityKeyType { |
22 | 25 | ATTRIBUTE = 'ATTRIBUTE', |
... | ... | @@ -27,6 +30,20 @@ export enum EntityKeyType { |
27 | 30 | ENTITY_FIELD = 'ENTITY_FIELD' |
28 | 31 | } |
29 | 32 | |
33 | +export function entityKeyTypeToDataKeyType(entityKeyType: EntityKeyType): DataKeyType { | |
34 | + switch (entityKeyType) { | |
35 | + case EntityKeyType.ATTRIBUTE: | |
36 | + case EntityKeyType.CLIENT_ATTRIBUTE: | |
37 | + case EntityKeyType.SHARED_ATTRIBUTE: | |
38 | + case EntityKeyType.SERVER_ATTRIBUTE: | |
39 | + return DataKeyType.attribute | |
40 | + case EntityKeyType.TIME_SERIES: | |
41 | + return DataKeyType.timeseries; | |
42 | + case EntityKeyType.ENTITY_FIELD: | |
43 | + return DataKeyType.entityField; | |
44 | + } | |
45 | +} | |
46 | + | |
30 | 47 | export interface EntityKey { |
31 | 48 | type: EntityKeyType; |
32 | 49 | key: string; |
... | ... | @@ -168,3 +185,25 @@ export interface EntityData { |
168 | 185 | latest: {[entityKeyType: string]: {[key: string]: TsValue}}; |
169 | 186 | timeseries: {[key: string]: Array<TsValue>}; |
170 | 187 | } |
188 | + | |
189 | +export function entityDataToEntityInfo(entityData: EntityData): EntityInfo { | |
190 | + const entityInfo: EntityInfo = { | |
191 | + id: entityData.entityId.id, | |
192 | + entityType: entityData.entityId.entityType as EntityType | |
193 | + }; | |
194 | + if (entityData.latest && entityData.latest[EntityKeyType.ENTITY_FIELD]) { | |
195 | + const fields = entityData.latest[EntityKeyType.ENTITY_FIELD]; | |
196 | + if (fields.name) { | |
197 | + entityInfo.name = fields.name.value; | |
198 | + } else { | |
199 | + entityInfo.name = ''; | |
200 | + } | |
201 | + if (fields.label) { | |
202 | + entityInfo.label = fields.label.value; | |
203 | + } else { | |
204 | + entityInfo.label = ''; | |
205 | + } | |
206 | + entityInfo.entityDescription = 'TODO: Not implemented'; | |
207 | + } | |
208 | + return entityInfo; | |
209 | +} | ... | ... |