Commit 99c9c099ba2e61d4a3ce917e2c2464bb81a694e3
1 parent
2b711151
Add Entity Type alias. Fix Key filter value conditional processing.
Showing
11 changed files
with
89 additions
and
40 deletions
... | ... | @@ -155,7 +155,7 @@ export class EntityDataSubscription { |
155 | 155 | clearTimeout(this.timer); |
156 | 156 | this.timer = null; |
157 | 157 | } |
158 | - if (this.datasourceType === DatasourceType.entity) { | |
158 | + if (this.datasourceType === DatasourceType.entity || this.datasourceType === DatasourceType.entityCount) { | |
159 | 159 | if (this.subscriber) { |
160 | 160 | this.subscriber.unsubscribe(); |
161 | 161 | this.subscriber = null; |
... | ... | @@ -318,24 +318,30 @@ export class EntityDataSubscription { |
318 | 318 | entityType: null |
319 | 319 | }; |
320 | 320 | |
321 | - const entityData: EntityData = { | |
322 | - entityId, | |
323 | - timeseries: {}, | |
324 | - latest: {} | |
325 | - }; | |
326 | - entityData.latest[EntityKeyType.ENTITY_FIELD] = { | |
327 | - name: {ts: Date.now(), value: DatasourceType.entityCount}, | |
328 | - }; | |
329 | - | |
330 | 321 | const countKey = this.entityDataSubscriptionOptions.dataKeys[0]; |
331 | 322 | |
323 | + let dataReceived = false; | |
324 | + | |
332 | 325 | this.subscriber.entityCount$.subscribe( |
333 | 326 | (entityCountUpdate) => { |
334 | - if (!entityData.latest[EntityKeyType.COUNT]) { | |
335 | - entityData.latest[EntityKeyType.COUNT] = {}; | |
336 | - entityData.latest[EntityKeyType.COUNT][countKey.name] = { | |
337 | - ts: Date.now(), | |
338 | - value: entityCountUpdate.count + '' | |
327 | + if (!dataReceived) { | |
328 | + const entityData: EntityData = { | |
329 | + entityId, | |
330 | + latest: { | |
331 | + [EntityKeyType.ENTITY_FIELD]: { | |
332 | + name: { | |
333 | + ts: Date.now(), | |
334 | + value: DatasourceType.entityCount | |
335 | + } | |
336 | + }, | |
337 | + [EntityKeyType.COUNT]: { | |
338 | + [countKey.name]: { | |
339 | + ts: Date.now(), | |
340 | + value: entityCountUpdate.count + '' | |
341 | + } | |
342 | + } | |
343 | + }, | |
344 | + timeseries: {} | |
339 | 345 | }; |
340 | 346 | const pageData: PageData<EntityData> = { |
341 | 347 | data: [entityData], |
... | ... | @@ -344,12 +350,20 @@ export class EntityDataSubscription { |
344 | 350 | totalPages: 1 |
345 | 351 | }; |
346 | 352 | this.onPageData(pageData); |
353 | + dataReceived = true; | |
347 | 354 | } else { |
348 | - const update = [deepClone(entityData)]; | |
349 | - update[0].latest[EntityKeyType.COUNT][countKey.name] = { | |
350 | - ts: Date.now(), | |
351 | - value: entityCountUpdate.count + '' | |
352 | - }; | |
355 | + const update: EntityData[] = [{ | |
356 | + entityId, | |
357 | + latest: { | |
358 | + [EntityKeyType.COUNT]: { | |
359 | + [countKey.name]: { | |
360 | + ts: Date.now(), | |
361 | + value: entityCountUpdate.count + '' | |
362 | + } | |
363 | + } | |
364 | + }, | |
365 | + timeseries: {} | |
366 | + }]; | |
353 | 367 | this.onDataUpdate(update); |
354 | 368 | } |
355 | 369 | } | ... | ... |
... | ... | @@ -481,6 +481,8 @@ export class EntityService { |
481 | 481 | return entityTypes.indexOf(filter.entityType) > -1 ? true : false; |
482 | 482 | case AliasFilterType.entityName: |
483 | 483 | return entityTypes.indexOf(filter.entityType) > -1 ? true : false; |
484 | + case AliasFilterType.entityType: | |
485 | + return entityTypes.indexOf(filter.entityType) > -1 ? true : false; | |
484 | 486 | case AliasFilterType.stateEntity: |
485 | 487 | return true; |
486 | 488 | case AliasFilterType.assetType: |
... | ... | @@ -540,6 +542,8 @@ export class EntityService { |
540 | 542 | return true; |
541 | 543 | case AliasFilterType.entityName: |
542 | 544 | return true; |
545 | + case AliasFilterType.entityType: | |
546 | + return true; | |
543 | 547 | case AliasFilterType.stateEntity: |
544 | 548 | return true; |
545 | 549 | case AliasFilterType.assetType: |
... | ... | @@ -805,6 +809,9 @@ export class EntityService { |
805 | 809 | case AliasFilterType.entityName: |
806 | 810 | result.entityFilter = deepClone(filter); |
807 | 811 | return of(result); |
812 | + case AliasFilterType.entityType: | |
813 | + result.entityFilter = deepClone(filter); | |
814 | + return of(result); | |
808 | 815 | case AliasFilterType.stateEntity: |
809 | 816 | result.stateEntity = true; |
810 | 817 | if (stateEntityId) { | ... | ... |
... | ... | @@ -76,6 +76,10 @@ export class EntityFilterViewComponent implements ControlValueAccessor { |
76 | 76 | this.filterDisplayValue = this.translate.instant(entityTypeTranslations.get(entityType).nameStartsWith, |
77 | 77 | {prefix}); |
78 | 78 | break; |
79 | + case AliasFilterType.entityType: | |
80 | + entityType = this.filter.entityType; | |
81 | + this.filterDisplayValue = this.translate.instant(entityTypeTranslations.get(entityType).typePlural); | |
82 | + break; | |
79 | 83 | case AliasFilterType.stateEntity: |
80 | 84 | this.filterDisplayValue = this.translate.instant('alias.filter-type-state-entity-description'); |
81 | 85 | break; | ... | ... |
... | ... | @@ -59,6 +59,13 @@ |
59 | 59 | </mat-error> |
60 | 60 | </mat-form-field> |
61 | 61 | </ng-template> |
62 | + <ng-template [ngSwitchCase]="aliasFilterType.entityType"> | |
63 | + <tb-entity-type-select required | |
64 | + showLabel | |
65 | + [allowedEntityTypes]="allowedEntityTypes" | |
66 | + formControlName="entityType"> | |
67 | + </tb-entity-type-select> | |
68 | + </ng-template> | |
62 | 69 | <ng-template [ngSwitchCase]="aliasFilterType.stateEntity"> |
63 | 70 | <mat-form-field floatLabel="always" class="mat-block"> |
64 | 71 | <mat-label translate>alias.state-entity-parameter-name</mat-label> | ... | ... |
... | ... | @@ -123,6 +123,11 @@ export class EntityFilterComponent implements ControlValueAccessor, OnInit { |
123 | 123 | entityNameFilter: [filter ? filter.entityNameFilter : '', [Validators.required]], |
124 | 124 | }); |
125 | 125 | break; |
126 | + case AliasFilterType.entityType: | |
127 | + this.filterFormGroup = this.fb.group({ | |
128 | + entityType: [filter ? filter.entityType : null, [Validators.required]] | |
129 | + }); | |
130 | + break; | |
126 | 131 | case AliasFilterType.stateEntity: |
127 | 132 | this.filterFormGroup = this.fb.group({ |
128 | 133 | stateEntityParamName: [filter ? filter.stateEntityParamName : null, []], | ... | ... |
... | ... | @@ -107,12 +107,15 @@ export class KeyFilterDialogComponent extends |
107 | 107 | key: [this.data.keyFilter.key.key, [Validators.required]] |
108 | 108 | } |
109 | 109 | ), |
110 | - value: [this.data.keyFilter.value], | |
111 | 110 | valueType: [this.data.keyFilter.valueType, [Validators.required]], |
112 | 111 | predicates: [this.data.keyFilter.predicates, [Validators.required]] |
113 | 112 | } |
114 | 113 | ); |
115 | - | |
114 | + if (this.data.telemetryKeysOnly) { | |
115 | + this.keyFilterFormGroup.addControl( | |
116 | + 'value', this.fb.control(this.data.keyFilter.value) | |
117 | + ); | |
118 | + } | |
116 | 119 | if (!this.data.readonly) { |
117 | 120 | this.keyFilterFormGroup.get('valueType').valueChanges.pipe( |
118 | 121 | takeUntil(this.destroy$) |
... | ... | @@ -144,12 +147,14 @@ export class KeyFilterDialogComponent extends |
144 | 147 | } else { |
145 | 148 | this.showAutocomplete = false; |
146 | 149 | } |
147 | - if (type === EntityKeyType.CONSTANT) { | |
148 | - this.keyFilterFormGroup.get('value').setValidators(Validators.required); | |
149 | - this.keyFilterFormGroup.get('value').updateValueAndValidity(); | |
150 | - } else { | |
151 | - this.keyFilterFormGroup.get('value').clearValidators(); | |
152 | - this.keyFilterFormGroup.get('value').updateValueAndValidity(); | |
150 | + if (this.data.telemetryKeysOnly) { | |
151 | + if (type === EntityKeyType.CONSTANT) { | |
152 | + this.keyFilterFormGroup.get('value').setValidators(Validators.required); | |
153 | + this.keyFilterFormGroup.get('value').updateValueAndValidity(); | |
154 | + } else { | |
155 | + this.keyFilterFormGroup.get('value').clearValidators(); | |
156 | + this.keyFilterFormGroup.get('value').updateValueAndValidity(); | |
157 | + } | |
153 | 158 | } |
154 | 159 | }); |
155 | 160 | ... | ... |
... | ... | @@ -24,7 +24,7 @@ import { |
24 | 24 | NG_VALUE_ACCESSOR |
25 | 25 | } from '@angular/forms'; |
26 | 26 | import { AliasEntityType, EntityType } from '@shared/models/entity-type.models'; |
27 | -import { EntityTypeFilter } from '@shared/models/relation.models'; | |
27 | +import { RelationEntityTypeFilter } from '@shared/models/relation.models'; | |
28 | 28 | import { PageComponent } from '@shared/components/page.component'; |
29 | 29 | import { Store } from '@ngrx/store'; |
30 | 30 | import { AppState } from '@core/core.state'; |
... | ... | @@ -80,7 +80,7 @@ export class RelationFiltersComponent extends PageComponent implements ControlVa |
80 | 80 | this.disabled = isDisabled; |
81 | 81 | } |
82 | 82 | |
83 | - writeValue(filters: Array<EntityTypeFilter>): void { | |
83 | + writeValue(filters: Array<RelationEntityTypeFilter>): void { | |
84 | 84 | if (this.valueChangeSubscription) { |
85 | 85 | this.valueChangeSubscription.unsubscribe(); |
86 | 86 | } |
... | ... | @@ -102,14 +102,14 @@ export class RelationFiltersComponent extends PageComponent implements ControlVa |
102 | 102 | |
103 | 103 | public addFilter() { |
104 | 104 | const relationFiltersFormArray = this.relationFiltersFormGroup.get('relationFilters') as FormArray; |
105 | - const filter: EntityTypeFilter = { | |
105 | + const filter: RelationEntityTypeFilter = { | |
106 | 106 | relationType: null, |
107 | 107 | entityTypes: [] |
108 | 108 | }; |
109 | 109 | relationFiltersFormArray.push(this.createRelationFilterFormGroup(filter)); |
110 | 110 | } |
111 | 111 | |
112 | - private createRelationFilterFormGroup(filter: EntityTypeFilter): AbstractControl { | |
112 | + private createRelationFilterFormGroup(filter: RelationEntityTypeFilter): AbstractControl { | |
113 | 113 | return this.fb.group({ |
114 | 114 | relationType: [filter ? filter.relationType : null], |
115 | 115 | entityTypes: [filter ? filter.entityTypes : []] |
... | ... | @@ -117,7 +117,7 @@ export class RelationFiltersComponent extends PageComponent implements ControlVa |
117 | 117 | } |
118 | 118 | |
119 | 119 | private updateModel() { |
120 | - const filters: Array<EntityTypeFilter> = this.relationFiltersFormGroup.get('relationFilters').value; | |
120 | + const filters: Array<RelationEntityTypeFilter> = this.relationFiltersFormGroup.get('relationFilters').value; | |
121 | 121 | this.propagateChange(filters); |
122 | 122 | } |
123 | 123 | } | ... | ... |
... | ... | @@ -16,14 +16,14 @@ |
16 | 16 | |
17 | 17 | import { EntityType } from '@shared/models/entity-type.models'; |
18 | 18 | import { EntityId } from '@shared/models/id/entity-id'; |
19 | -import { EntitySearchDirection, EntityTypeFilter } from '@shared/models/relation.models'; | |
20 | -import { EntityInfo } from './entity.models'; | |
19 | +import { EntitySearchDirection, RelationEntityTypeFilter } from '@shared/models/relation.models'; | |
21 | 20 | import { EntityFilter } from '@shared/models/query/query.models'; |
22 | 21 | |
23 | 22 | export enum AliasFilterType { |
24 | 23 | singleEntity = 'singleEntity', |
25 | 24 | entityList = 'entityList', |
26 | 25 | entityName = 'entityName', |
26 | + entityType = 'entityType', | |
27 | 27 | stateEntity = 'stateEntity', |
28 | 28 | assetType = 'assetType', |
29 | 29 | deviceType = 'deviceType', |
... | ... | @@ -40,6 +40,7 @@ export const aliasFilterTypeTranslationMap = new Map<AliasFilterType, string>( |
40 | 40 | [ AliasFilterType.singleEntity, 'alias.filter-type-single-entity' ], |
41 | 41 | [ AliasFilterType.entityList, 'alias.filter-type-entity-list' ], |
42 | 42 | [ AliasFilterType.entityName, 'alias.filter-type-entity-name' ], |
43 | + [ AliasFilterType.entityType, 'alias.filter-type-entity-type' ], | |
43 | 44 | [ AliasFilterType.stateEntity, 'alias.filter-type-state-entity' ], |
44 | 45 | [ AliasFilterType.assetType, 'alias.filter-type-asset-type' ], |
45 | 46 | [ AliasFilterType.deviceType, 'alias.filter-type-device-type' ], |
... | ... | @@ -66,6 +67,10 @@ export interface EntityNameFilter { |
66 | 67 | entityNameFilter?: string; |
67 | 68 | } |
68 | 69 | |
70 | +export interface EntityTypeFilter { | |
71 | + entityType?: EntityType; | |
72 | +} | |
73 | + | |
69 | 74 | export interface StateEntityFilter { |
70 | 75 | stateEntityParamName?: string; |
71 | 76 | defaultStateEntity?: EntityId; |
... | ... | @@ -92,7 +97,7 @@ export interface RelationsQueryFilter { |
92 | 97 | defaultStateEntity?: EntityId; |
93 | 98 | rootEntity?: EntityId; |
94 | 99 | direction?: EntitySearchDirection; |
95 | - filters?: Array<EntityTypeFilter>; | |
100 | + filters?: Array<RelationEntityTypeFilter>; | |
96 | 101 | maxLevel?: number; |
97 | 102 | fetchLastLevelOnly?: boolean; |
98 | 103 | } |
... | ... | @@ -129,6 +134,7 @@ export type EntityFilters = |
129 | 134 | SingleEntityFilter & |
130 | 135 | EntityListFilter & |
131 | 136 | EntityNameFilter & |
137 | + EntityTypeFilter & | |
132 | 138 | StateEntityFilter & |
133 | 139 | AssetTypeFilter & |
134 | 140 | DeviceTypeFilter & | ... | ... |
... | ... | @@ -351,14 +351,14 @@ export interface KeyFilterPredicateInfo { |
351 | 351 | export interface KeyFilter { |
352 | 352 | key: EntityKey; |
353 | 353 | valueType: EntityKeyValueType; |
354 | - value: string | number | boolean; | |
354 | + value?: string | number | boolean; | |
355 | 355 | predicate: KeyFilterPredicate; |
356 | 356 | } |
357 | 357 | |
358 | 358 | export interface KeyFilterInfo { |
359 | 359 | key: EntityKey; |
360 | 360 | valueType: EntityKeyValueType; |
361 | - value: string | number | boolean; | |
361 | + value?: string | number | boolean; | |
362 | 362 | predicates: Array<KeyFilterPredicateInfo>; |
363 | 363 | } |
364 | 364 | ... | ... |
... | ... | @@ -52,7 +52,7 @@ export const directionTypeTranslations = new Map<EntitySearchDirection, string>( |
52 | 52 | ] |
53 | 53 | ); |
54 | 54 | |
55 | -export interface EntityTypeFilter { | |
55 | +export interface RelationEntityTypeFilter { | |
56 | 56 | relationType: string; |
57 | 57 | entityTypes: Array<EntityType>; |
58 | 58 | } |
... | ... | @@ -68,7 +68,7 @@ export interface RelationsSearchParameters { |
68 | 68 | |
69 | 69 | export interface EntityRelationsQuery { |
70 | 70 | parameters: RelationsSearchParameters; |
71 | - filters: Array<EntityTypeFilter>; | |
71 | + filters: Array<RelationEntityTypeFilter>; | |
72 | 72 | } |
73 | 73 | |
74 | 74 | export interface EntitySearchQuery { | ... | ... |
... | ... | @@ -299,6 +299,7 @@ |
299 | 299 | "filter-type-single-entity": "Single entity", |
300 | 300 | "filter-type-entity-list": "Entity list", |
301 | 301 | "filter-type-entity-name": "Entity name", |
302 | + "filter-type-entity-type": "Entity type", | |
302 | 303 | "filter-type-state-entity": "Entity from dashboard state", |
303 | 304 | "filter-type-state-entity-description": "Entity taken from dashboard state parameters", |
304 | 305 | "filter-type-asset-type": "Asset type", | ... | ... |