Add Entity Type alias. Fix Key filter value conditional processing.

This commit is contained in:
Igor Kulikov 2021-03-02 15:13:21 +02:00
parent 2b7111516c
commit 99c9c099ba
11 changed files with 89 additions and 40 deletions

View File

@ -155,7 +155,7 @@ export class EntityDataSubscription {
clearTimeout(this.timer); clearTimeout(this.timer);
this.timer = null; this.timer = null;
} }
if (this.datasourceType === DatasourceType.entity) { if (this.datasourceType === DatasourceType.entity || this.datasourceType === DatasourceType.entityCount) {
if (this.subscriber) { if (this.subscriber) {
this.subscriber.unsubscribe(); this.subscriber.unsubscribe();
this.subscriber = null; this.subscriber = null;
@ -318,24 +318,30 @@ export class EntityDataSubscription {
entityType: null entityType: null
}; };
const entityData: EntityData = {
entityId,
timeseries: {},
latest: {}
};
entityData.latest[EntityKeyType.ENTITY_FIELD] = {
name: {ts: Date.now(), value: DatasourceType.entityCount},
};
const countKey = this.entityDataSubscriptionOptions.dataKeys[0]; const countKey = this.entityDataSubscriptionOptions.dataKeys[0];
let dataReceived = false;
this.subscriber.entityCount$.subscribe( this.subscriber.entityCount$.subscribe(
(entityCountUpdate) => { (entityCountUpdate) => {
if (!entityData.latest[EntityKeyType.COUNT]) { if (!dataReceived) {
entityData.latest[EntityKeyType.COUNT] = {}; const entityData: EntityData = {
entityData.latest[EntityKeyType.COUNT][countKey.name] = { entityId,
ts: Date.now(), latest: {
value: entityCountUpdate.count + '' [EntityKeyType.ENTITY_FIELD]: {
name: {
ts: Date.now(),
value: DatasourceType.entityCount
}
},
[EntityKeyType.COUNT]: {
[countKey.name]: {
ts: Date.now(),
value: entityCountUpdate.count + ''
}
}
},
timeseries: {}
}; };
const pageData: PageData<EntityData> = { const pageData: PageData<EntityData> = {
data: [entityData], data: [entityData],
@ -344,12 +350,20 @@ export class EntityDataSubscription {
totalPages: 1 totalPages: 1
}; };
this.onPageData(pageData); this.onPageData(pageData);
dataReceived = true;
} else { } else {
const update = [deepClone(entityData)]; const update: EntityData[] = [{
update[0].latest[EntityKeyType.COUNT][countKey.name] = { entityId,
ts: Date.now(), latest: {
value: entityCountUpdate.count + '' [EntityKeyType.COUNT]: {
}; [countKey.name]: {
ts: Date.now(),
value: entityCountUpdate.count + ''
}
}
},
timeseries: {}
}];
this.onDataUpdate(update); this.onDataUpdate(update);
} }
} }

View File

@ -481,6 +481,8 @@ export class EntityService {
return entityTypes.indexOf(filter.entityType) > -1 ? true : false; return entityTypes.indexOf(filter.entityType) > -1 ? true : false;
case AliasFilterType.entityName: case AliasFilterType.entityName:
return entityTypes.indexOf(filter.entityType) > -1 ? true : false; return entityTypes.indexOf(filter.entityType) > -1 ? true : false;
case AliasFilterType.entityType:
return entityTypes.indexOf(filter.entityType) > -1 ? true : false;
case AliasFilterType.stateEntity: case AliasFilterType.stateEntity:
return true; return true;
case AliasFilterType.assetType: case AliasFilterType.assetType:
@ -540,6 +542,8 @@ export class EntityService {
return true; return true;
case AliasFilterType.entityName: case AliasFilterType.entityName:
return true; return true;
case AliasFilterType.entityType:
return true;
case AliasFilterType.stateEntity: case AliasFilterType.stateEntity:
return true; return true;
case AliasFilterType.assetType: case AliasFilterType.assetType:
@ -805,6 +809,9 @@ export class EntityService {
case AliasFilterType.entityName: case AliasFilterType.entityName:
result.entityFilter = deepClone(filter); result.entityFilter = deepClone(filter);
return of(result); return of(result);
case AliasFilterType.entityType:
result.entityFilter = deepClone(filter);
return of(result);
case AliasFilterType.stateEntity: case AliasFilterType.stateEntity:
result.stateEntity = true; result.stateEntity = true;
if (stateEntityId) { if (stateEntityId) {

View File

@ -76,6 +76,10 @@ export class EntityFilterViewComponent implements ControlValueAccessor {
this.filterDisplayValue = this.translate.instant(entityTypeTranslations.get(entityType).nameStartsWith, this.filterDisplayValue = this.translate.instant(entityTypeTranslations.get(entityType).nameStartsWith,
{prefix}); {prefix});
break; break;
case AliasFilterType.entityType:
entityType = this.filter.entityType;
this.filterDisplayValue = this.translate.instant(entityTypeTranslations.get(entityType).typePlural);
break;
case AliasFilterType.stateEntity: case AliasFilterType.stateEntity:
this.filterDisplayValue = this.translate.instant('alias.filter-type-state-entity-description'); this.filterDisplayValue = this.translate.instant('alias.filter-type-state-entity-description');
break; break;

View File

@ -59,6 +59,13 @@
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
</ng-template> </ng-template>
<ng-template [ngSwitchCase]="aliasFilterType.entityType">
<tb-entity-type-select required
showLabel
[allowedEntityTypes]="allowedEntityTypes"
formControlName="entityType">
</tb-entity-type-select>
</ng-template>
<ng-template [ngSwitchCase]="aliasFilterType.stateEntity"> <ng-template [ngSwitchCase]="aliasFilterType.stateEntity">
<mat-form-field floatLabel="always" class="mat-block"> <mat-form-field floatLabel="always" class="mat-block">
<mat-label translate>alias.state-entity-parameter-name</mat-label> <mat-label translate>alias.state-entity-parameter-name</mat-label>

View File

@ -123,6 +123,11 @@ export class EntityFilterComponent implements ControlValueAccessor, OnInit {
entityNameFilter: [filter ? filter.entityNameFilter : '', [Validators.required]], entityNameFilter: [filter ? filter.entityNameFilter : '', [Validators.required]],
}); });
break; break;
case AliasFilterType.entityType:
this.filterFormGroup = this.fb.group({
entityType: [filter ? filter.entityType : null, [Validators.required]]
});
break;
case AliasFilterType.stateEntity: case AliasFilterType.stateEntity:
this.filterFormGroup = this.fb.group({ this.filterFormGroup = this.fb.group({
stateEntityParamName: [filter ? filter.stateEntityParamName : null, []], stateEntityParamName: [filter ? filter.stateEntityParamName : null, []],

View File

@ -107,12 +107,15 @@ export class KeyFilterDialogComponent extends
key: [this.data.keyFilter.key.key, [Validators.required]] key: [this.data.keyFilter.key.key, [Validators.required]]
} }
), ),
value: [this.data.keyFilter.value],
valueType: [this.data.keyFilter.valueType, [Validators.required]], valueType: [this.data.keyFilter.valueType, [Validators.required]],
predicates: [this.data.keyFilter.predicates, [Validators.required]] predicates: [this.data.keyFilter.predicates, [Validators.required]]
} }
); );
if (this.data.telemetryKeysOnly) {
this.keyFilterFormGroup.addControl(
'value', this.fb.control(this.data.keyFilter.value)
);
}
if (!this.data.readonly) { if (!this.data.readonly) {
this.keyFilterFormGroup.get('valueType').valueChanges.pipe( this.keyFilterFormGroup.get('valueType').valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)
@ -144,12 +147,14 @@ export class KeyFilterDialogComponent extends
} else { } else {
this.showAutocomplete = false; this.showAutocomplete = false;
} }
if (type === EntityKeyType.CONSTANT) { if (this.data.telemetryKeysOnly) {
this.keyFilterFormGroup.get('value').setValidators(Validators.required); if (type === EntityKeyType.CONSTANT) {
this.keyFilterFormGroup.get('value').updateValueAndValidity(); this.keyFilterFormGroup.get('value').setValidators(Validators.required);
} else { this.keyFilterFormGroup.get('value').updateValueAndValidity();
this.keyFilterFormGroup.get('value').clearValidators(); } else {
this.keyFilterFormGroup.get('value').updateValueAndValidity(); this.keyFilterFormGroup.get('value').clearValidators();
this.keyFilterFormGroup.get('value').updateValueAndValidity();
}
} }
}); });

View File

@ -24,7 +24,7 @@ import {
NG_VALUE_ACCESSOR NG_VALUE_ACCESSOR
} from '@angular/forms'; } from '@angular/forms';
import { AliasEntityType, EntityType } from '@shared/models/entity-type.models'; import { AliasEntityType, EntityType } from '@shared/models/entity-type.models';
import { EntityTypeFilter } from '@shared/models/relation.models'; import { RelationEntityTypeFilter } from '@shared/models/relation.models';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
@ -80,7 +80,7 @@ export class RelationFiltersComponent extends PageComponent implements ControlVa
this.disabled = isDisabled; this.disabled = isDisabled;
} }
writeValue(filters: Array<EntityTypeFilter>): void { writeValue(filters: Array<RelationEntityTypeFilter>): void {
if (this.valueChangeSubscription) { if (this.valueChangeSubscription) {
this.valueChangeSubscription.unsubscribe(); this.valueChangeSubscription.unsubscribe();
} }
@ -102,14 +102,14 @@ export class RelationFiltersComponent extends PageComponent implements ControlVa
public addFilter() { public addFilter() {
const relationFiltersFormArray = this.relationFiltersFormGroup.get('relationFilters') as FormArray; const relationFiltersFormArray = this.relationFiltersFormGroup.get('relationFilters') as FormArray;
const filter: EntityTypeFilter = { const filter: RelationEntityTypeFilter = {
relationType: null, relationType: null,
entityTypes: [] entityTypes: []
}; };
relationFiltersFormArray.push(this.createRelationFilterFormGroup(filter)); relationFiltersFormArray.push(this.createRelationFilterFormGroup(filter));
} }
private createRelationFilterFormGroup(filter: EntityTypeFilter): AbstractControl { private createRelationFilterFormGroup(filter: RelationEntityTypeFilter): AbstractControl {
return this.fb.group({ return this.fb.group({
relationType: [filter ? filter.relationType : null], relationType: [filter ? filter.relationType : null],
entityTypes: [filter ? filter.entityTypes : []] entityTypes: [filter ? filter.entityTypes : []]
@ -117,7 +117,7 @@ export class RelationFiltersComponent extends PageComponent implements ControlVa
} }
private updateModel() { private updateModel() {
const filters: Array<EntityTypeFilter> = this.relationFiltersFormGroup.get('relationFilters').value; const filters: Array<RelationEntityTypeFilter> = this.relationFiltersFormGroup.get('relationFilters').value;
this.propagateChange(filters); this.propagateChange(filters);
} }
} }

View File

@ -16,14 +16,14 @@
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import { EntityId } from '@shared/models/id/entity-id'; import { EntityId } from '@shared/models/id/entity-id';
import { EntitySearchDirection, EntityTypeFilter } from '@shared/models/relation.models'; import { EntitySearchDirection, RelationEntityTypeFilter } from '@shared/models/relation.models';
import { EntityInfo } from './entity.models';
import { EntityFilter } from '@shared/models/query/query.models'; import { EntityFilter } from '@shared/models/query/query.models';
export enum AliasFilterType { export enum AliasFilterType {
singleEntity = 'singleEntity', singleEntity = 'singleEntity',
entityList = 'entityList', entityList = 'entityList',
entityName = 'entityName', entityName = 'entityName',
entityType = 'entityType',
stateEntity = 'stateEntity', stateEntity = 'stateEntity',
assetType = 'assetType', assetType = 'assetType',
deviceType = 'deviceType', deviceType = 'deviceType',
@ -40,6 +40,7 @@ export const aliasFilterTypeTranslationMap = new Map<AliasFilterType, string>(
[ AliasFilterType.singleEntity, 'alias.filter-type-single-entity' ], [ AliasFilterType.singleEntity, 'alias.filter-type-single-entity' ],
[ AliasFilterType.entityList, 'alias.filter-type-entity-list' ], [ AliasFilterType.entityList, 'alias.filter-type-entity-list' ],
[ AliasFilterType.entityName, 'alias.filter-type-entity-name' ], [ AliasFilterType.entityName, 'alias.filter-type-entity-name' ],
[ AliasFilterType.entityType, 'alias.filter-type-entity-type' ],
[ AliasFilterType.stateEntity, 'alias.filter-type-state-entity' ], [ AliasFilterType.stateEntity, 'alias.filter-type-state-entity' ],
[ AliasFilterType.assetType, 'alias.filter-type-asset-type' ], [ AliasFilterType.assetType, 'alias.filter-type-asset-type' ],
[ AliasFilterType.deviceType, 'alias.filter-type-device-type' ], [ AliasFilterType.deviceType, 'alias.filter-type-device-type' ],
@ -66,6 +67,10 @@ export interface EntityNameFilter {
entityNameFilter?: string; entityNameFilter?: string;
} }
export interface EntityTypeFilter {
entityType?: EntityType;
}
export interface StateEntityFilter { export interface StateEntityFilter {
stateEntityParamName?: string; stateEntityParamName?: string;
defaultStateEntity?: EntityId; defaultStateEntity?: EntityId;
@ -92,7 +97,7 @@ export interface RelationsQueryFilter {
defaultStateEntity?: EntityId; defaultStateEntity?: EntityId;
rootEntity?: EntityId; rootEntity?: EntityId;
direction?: EntitySearchDirection; direction?: EntitySearchDirection;
filters?: Array<EntityTypeFilter>; filters?: Array<RelationEntityTypeFilter>;
maxLevel?: number; maxLevel?: number;
fetchLastLevelOnly?: boolean; fetchLastLevelOnly?: boolean;
} }
@ -129,6 +134,7 @@ export type EntityFilters =
SingleEntityFilter & SingleEntityFilter &
EntityListFilter & EntityListFilter &
EntityNameFilter & EntityNameFilter &
EntityTypeFilter &
StateEntityFilter & StateEntityFilter &
AssetTypeFilter & AssetTypeFilter &
DeviceTypeFilter & DeviceTypeFilter &

View File

@ -351,14 +351,14 @@ export interface KeyFilterPredicateInfo {
export interface KeyFilter { export interface KeyFilter {
key: EntityKey; key: EntityKey;
valueType: EntityKeyValueType; valueType: EntityKeyValueType;
value: string | number | boolean; value?: string | number | boolean;
predicate: KeyFilterPredicate; predicate: KeyFilterPredicate;
} }
export interface KeyFilterInfo { export interface KeyFilterInfo {
key: EntityKey; key: EntityKey;
valueType: EntityKeyValueType; valueType: EntityKeyValueType;
value: string | number | boolean; value?: string | number | boolean;
predicates: Array<KeyFilterPredicateInfo>; predicates: Array<KeyFilterPredicateInfo>;
} }

View File

@ -52,7 +52,7 @@ export const directionTypeTranslations = new Map<EntitySearchDirection, string>(
] ]
); );
export interface EntityTypeFilter { export interface RelationEntityTypeFilter {
relationType: string; relationType: string;
entityTypes: Array<EntityType>; entityTypes: Array<EntityType>;
} }
@ -68,7 +68,7 @@ export interface RelationsSearchParameters {
export interface EntityRelationsQuery { export interface EntityRelationsQuery {
parameters: RelationsSearchParameters; parameters: RelationsSearchParameters;
filters: Array<EntityTypeFilter>; filters: Array<RelationEntityTypeFilter>;
} }
export interface EntitySearchQuery { export interface EntitySearchQuery {

View File

@ -299,6 +299,7 @@
"filter-type-single-entity": "Single entity", "filter-type-single-entity": "Single entity",
"filter-type-entity-list": "Entity list", "filter-type-entity-list": "Entity list",
"filter-type-entity-name": "Entity name", "filter-type-entity-name": "Entity name",
"filter-type-entity-type": "Entity type",
"filter-type-state-entity": "Entity from dashboard state", "filter-type-state-entity": "Entity from dashboard state",
"filter-type-state-entity-description": "Entity taken from dashboard state parameters", "filter-type-state-entity-description": "Entity taken from dashboard state parameters",
"filter-type-asset-type": "Asset type", "filter-type-asset-type": "Asset type",