Commit ab93e5455c4348bf01ef85d5f84df66280ab2e4b

Authored by Igor Kulikov
1 parent be8460ad

UI: entity data fixes

@@ -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 +}