Showing
5 changed files
with
73 additions
and
44 deletions
@@ -23,6 +23,7 @@ import { | @@ -23,6 +23,7 @@ import { | ||
23 | EntityFilter, | 23 | EntityFilter, |
24 | EntityKey, | 24 | EntityKey, |
25 | EntityKeyType, | 25 | EntityKeyType, |
26 | + entityKeyTypeToDataKeyType, | ||
26 | KeyFilter, | 27 | KeyFilter, |
27 | TsValue | 28 | TsValue |
28 | } from '@shared/models/query/query.models'; | 29 | } from '@shared/models/query/query.models'; |
@@ -41,8 +42,8 @@ import { PageData } from '@shared/models/page/page-data'; | @@ -41,8 +42,8 @@ import { PageData } from '@shared/models/page/page-data'; | ||
41 | import { DataAggregator } from '@core/api/data-aggregator'; | 42 | import { DataAggregator } from '@core/api/data-aggregator'; |
42 | import { NULL_UUID } from '@shared/models/id/has-uuid'; | 43 | import { NULL_UUID } from '@shared/models/id/has-uuid'; |
43 | import { EntityType } from '@shared/models/entity-type.models'; | 44 | import { EntityType } from '@shared/models/entity-type.models'; |
44 | -import Timeout = NodeJS.Timeout; | ||
45 | import { Observable, of, ReplaySubject, Subject } from 'rxjs'; | 45 | import { Observable, of, ReplaySubject, Subject } from 'rxjs'; |
46 | +import Timeout = NodeJS.Timeout; | ||
46 | 47 | ||
47 | export interface EntityDataSubscriptionOptions { | 48 | export interface EntityDataSubscriptionOptions { |
48 | datasourceType: DatasourceType; | 49 | datasourceType: DatasourceType; |
@@ -473,7 +474,8 @@ export class EntityDataSubscription { | @@ -473,7 +474,8 @@ export class EntityDataSubscription { | ||
473 | if (this.entityDataSubscriptionOptions.type === widgetType.latest && entityData.latest) { | 474 | if (this.entityDataSubscriptionOptions.type === widgetType.latest && entityData.latest) { |
474 | for (const type of Object.keys(entityData.latest)) { | 475 | for (const type of Object.keys(entityData.latest)) { |
475 | const subscriptionData = this.toSubscriptionData(entityData.latest[type], false); | 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 | if (this.entityDataSubscriptionOptions.type === widgetType.timeseries && entityData.timeseries) { | 481 | if (this.entityDataSubscriptionOptions.type === widgetType.timeseries && entityData.timeseries) { |
@@ -486,7 +488,7 @@ export class EntityDataSubscription { | @@ -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 | dataUpdatedCb: DataUpdatedCb) { | 492 | dataUpdatedCb: DataUpdatedCb) { |
491 | for (const keyName of Object.keys(sourceData)) { | 493 | for (const keyName of Object.keys(sourceData)) { |
492 | const keyData = sourceData[keyName]; | 494 | const keyData = sourceData[keyName]; |
@@ -52,7 +52,13 @@ import { EntityId } from '@app/shared/models/id/entity-id'; | @@ -52,7 +52,13 @@ import { EntityId } from '@app/shared/models/id/entity-id'; | ||
52 | import * as moment_ from 'moment'; | 52 | import * as moment_ from 'moment'; |
53 | import { PageData } from '@shared/models/page/page-data'; | 53 | import { PageData } from '@shared/models/page/page-data'; |
54 | import { EntityDataListener } from '@core/api/entity-data.service'; | 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 | import { map } from 'rxjs/operators'; | 62 | import { map } from 'rxjs/operators'; |
57 | 63 | ||
58 | const moment = moment_; | 64 | const moment = moment_; |
@@ -414,6 +420,7 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -414,6 +420,7 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
414 | this.configureLoadedData(); | 420 | this.configureLoadedData(); |
415 | this.hasResolvedData = true; | 421 | this.hasResolvedData = true; |
416 | this.notifyDataLoaded(); | 422 | this.notifyDataLoaded(); |
423 | + this.onDataUpdated(true); | ||
417 | }) | 424 | }) |
418 | ); | 425 | ); |
419 | } | 426 | } |
@@ -881,7 +888,6 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -881,7 +888,6 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
881 | 888 | ||
882 | private dataSubscribe() { | 889 | private dataSubscribe() { |
883 | if (!this.hasDataPageLink) { | 890 | if (!this.hasDataPageLink) { |
884 | - this.notifyDataLoading(); | ||
885 | if (this.type === widgetType.timeseries && this.timeWindowConfig) { | 891 | if (this.type === widgetType.timeseries && this.timeWindowConfig) { |
886 | this.updateRealtimeSubscription(); | 892 | this.updateRealtimeSubscription(); |
887 | if (this.comparisonEnabled) { | 893 | if (this.comparisonEnabled) { |
@@ -897,7 +903,6 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -897,7 +903,6 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
897 | this.ctx.entityDataService.startSubscription(listener); | 903 | this.ctx.entityDataService.startSubscription(listener); |
898 | }); | 904 | }); |
899 | if (forceUpdate) { | 905 | if (forceUpdate) { |
900 | - this.notifyDataLoaded(); | ||
901 | this.onDataUpdated(); | 906 | this.onDataUpdated(); |
902 | } | 907 | } |
903 | } | 908 | } |
@@ -1269,23 +1274,11 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -1269,23 +1274,11 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
1269 | newDatasource.entityId = entityData.entityId.id; | 1274 | newDatasource.entityId = entityData.entityId.id; |
1270 | newDatasource.entityType = entityData.entityId.entityType as EntityType; | 1275 | newDatasource.entityType = entityData.entityId.entityType as EntityType; |
1271 | if (configDatasource.type === DatasourceType.entity) { | 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 | newDatasource.generated = index > 0 ? true : false; | 1283 | newDatasource.generated = index > 0 ? true : false; |
1291 | return newDatasource; | 1284 | return newDatasource; |
@@ -1296,7 +1289,6 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -1296,7 +1289,6 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
1296 | const startIndex = configuredDatasource.dataKeyStartIndex; | 1289 | const startIndex = configuredDatasource.dataKeyStartIndex; |
1297 | const dataKeysCount = configuredDatasource.dataKeys.length; | 1290 | const dataKeysCount = configuredDatasource.dataKeys.length; |
1298 | const index = startIndex + dataIndex*dataKeysCount + dataKeyIndex; | 1291 | const index = startIndex + dataIndex*dataKeysCount + dataKeyIndex; |
1299 | - this.notifyDataLoaded(); | ||
1300 | let update = true; | 1292 | let update = true; |
1301 | let currentData: DataSetHolder; | 1293 | let currentData: DataSetHolder; |
1302 | if (this.displayLegend && this.legendData.keys[index].dataKey.hidden) { | 1294 | if (this.displayLegend && this.legendData.keys[index].dataKey.hidden) { |
@@ -54,7 +54,7 @@ import { AttributeService } from '@core/http/attribute.service'; | @@ -54,7 +54,7 @@ import { AttributeService } from '@core/http/attribute.service'; | ||
54 | import { | 54 | import { |
55 | createDefaultEntityDataPageLink, | 55 | createDefaultEntityDataPageLink, |
56 | EntityData, | 56 | EntityData, |
57 | - EntityDataQuery, | 57 | + EntityDataQuery, entityDataToEntityInfo, |
58 | EntityFilter, | 58 | EntityFilter, |
59 | EntityKeyType | 59 | EntityKeyType |
60 | } from '@shared/models/query/query.models'; | 60 | } from '@shared/models/query/query.models'; |
@@ -365,23 +365,6 @@ export class EntityService { | @@ -365,23 +365,6 @@ export class EntityService { | ||
365 | return this.http.post<PageData<EntityData>>('/api/entitiesQuery/find', query, defaultHttpOptionsFromConfig(config)); | 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 | public findSingleEntityInfoByEntityFilter(filter: EntityFilter, config?: RequestConfig): Observable<EntityInfo> { | 368 | public findSingleEntityInfoByEntityFilter(filter: EntityFilter, config?: RequestConfig): Observable<EntityInfo> { |
386 | const query: EntityDataQuery = { | 369 | const query: EntityDataQuery = { |
387 | entityFilter: filter, | 370 | entityFilter: filter, |
@@ -401,7 +384,7 @@ export class EntityService { | @@ -401,7 +384,7 @@ export class EntityService { | ||
401 | map((data) => { | 384 | map((data) => { |
402 | if (data.data.length) { | 385 | if (data.data.length) { |
403 | const entityData = data.data[0]; | 386 | const entityData = data.data[0]; |
404 | - return this.entityDataToEntityInfo(entityData); | 387 | + return entityDataToEntityInfo(entityData); |
405 | } else { | 388 | } else { |
406 | return null; | 389 | return null; |
407 | } | 390 | } |
@@ -138,6 +138,8 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI | @@ -138,6 +138,8 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI | ||
138 | subscriptionInited = false; | 138 | subscriptionInited = false; |
139 | destroyed = false; | 139 | destroyed = false; |
140 | widgetSizeDetected = false; | 140 | widgetSizeDetected = false; |
141 | + widgetInstanceInited = false; | ||
142 | + dataUpdatePending = false; | ||
141 | 143 | ||
142 | cafs: {[cafId: string]: CancelAnimationFrame} = {}; | 144 | cafs: {[cafId: string]: CancelAnimationFrame} = {}; |
143 | 145 | ||
@@ -363,6 +365,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI | @@ -363,6 +365,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI | ||
363 | subscription.destroy(); | 365 | subscription.destroy(); |
364 | } | 366 | } |
365 | this.subscriptionInited = false; | 367 | this.subscriptionInited = false; |
368 | + this.dataUpdatePending = false; | ||
366 | this.widgetContext.subscriptions = {}; | 369 | this.widgetContext.subscriptions = {}; |
367 | if (this.widgetContext.inited) { | 370 | if (this.widgetContext.inited) { |
368 | this.widgetContext.inited = false; | 371 | this.widgetContext.inited = false; |
@@ -375,6 +378,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI | @@ -375,6 +378,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI | ||
375 | try { | 378 | try { |
376 | if (shouldDestroyWidgetInstance) { | 379 | if (shouldDestroyWidgetInstance) { |
377 | this.widgetTypeInstance.onDestroy(); | 380 | this.widgetTypeInstance.onDestroy(); |
381 | + this.widgetInstanceInited = false; | ||
378 | } | 382 | } |
379 | } catch (e) { | 383 | } catch (e) { |
380 | this.handleWidgetException(e); | 384 | this.handleWidgetException(e); |
@@ -479,6 +483,11 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI | @@ -479,6 +483,11 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI | ||
479 | try { | 483 | try { |
480 | if (this.displayWidgetInstance()) { | 484 | if (this.displayWidgetInstance()) { |
481 | this.widgetTypeInstance.onInit(); | 485 | this.widgetTypeInstance.onInit(); |
486 | + this.widgetInstanceInited = true; | ||
487 | + if (this.dataUpdatePending) { | ||
488 | + this.widgetTypeInstance.onDataUpdated(); | ||
489 | + this.dataUpdatePending = false; | ||
490 | + } | ||
482 | } else { | 491 | } else { |
483 | this.loadingData = false; | 492 | this.loadingData = false; |
484 | } | 493 | } |
@@ -798,7 +807,11 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI | @@ -798,7 +807,11 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI | ||
798 | onDataUpdated: () => { | 807 | onDataUpdated: () => { |
799 | try { | 808 | try { |
800 | if (this.displayWidgetInstance()) { | 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 | } catch (e){} | 816 | } catch (e){} |
804 | }, | 817 | }, |
@@ -17,6 +17,9 @@ | @@ -17,6 +17,9 @@ | ||
17 | import { AliasFilterType, EntityFilters } from '@shared/models/alias.models'; | 17 | import { AliasFilterType, EntityFilters } from '@shared/models/alias.models'; |
18 | import { EntityId } from '@shared/models/id/entity-id'; | 18 | import { EntityId } from '@shared/models/id/entity-id'; |
19 | import { SortDirection } from '@angular/material/sort'; | 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 | export enum EntityKeyType { | 24 | export enum EntityKeyType { |
22 | ATTRIBUTE = 'ATTRIBUTE', | 25 | ATTRIBUTE = 'ATTRIBUTE', |
@@ -27,6 +30,20 @@ export enum EntityKeyType { | @@ -27,6 +30,20 @@ export enum EntityKeyType { | ||
27 | ENTITY_FIELD = 'ENTITY_FIELD' | 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 | export interface EntityKey { | 47 | export interface EntityKey { |
31 | type: EntityKeyType; | 48 | type: EntityKeyType; |
32 | key: string; | 49 | key: string; |
@@ -168,3 +185,25 @@ export interface EntityData { | @@ -168,3 +185,25 @@ export interface EntityData { | ||
168 | latest: {[entityKeyType: string]: {[key: string]: TsValue}}; | 185 | latest: {[entityKeyType: string]: {[key: string]: TsValue}}; |
169 | timeseries: {[key: string]: Array<TsValue>}; | 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 | +} |