From 7effa018ce6147809e84efc83fb4361464d23a12 Mon Sep 17 00:00:00 2001 From: rusikv Date: Fri, 5 Jan 2024 15:43:29 +0200 Subject: [PATCH] UI: added getEntitySubtypesObservable method to entity service, code cleanup --- ui-ngx/src/app/core/http/entity.service.ts | 27 ++++++ .../entity-subtype-autocomplete.component.ts | 49 ++++------- .../entity/entity-subtype-list.component.ts | 26 +----- .../entity/entity-subtype-select.component.ts | 83 ++++++------------- 4 files changed, 73 insertions(+), 112 deletions(-) diff --git a/ui-ngx/src/app/core/http/entity.service.ts b/ui-ngx/src/app/core/http/entity.service.ts index 968329d36a..677db94512 100644 --- a/ui-ngx/src/app/core/http/entity.service.ts +++ b/ui-ngx/src/app/core/http/entity.service.ts @@ -1519,4 +1519,31 @@ export class EntityService { } return entityObservable; } + + public getEntitySubtypesObservable(entityType: EntityType): Observable> { + let observable: Observable>; + switch (entityType) { + case EntityType.ASSET: + observable = this.assetProfileService.getAssetProfileNames(false, {ignoreLoading: true}).pipe( + map(subTypes => subTypes.map(subType => subType.name)) + ); + break; + case EntityType.DEVICE: + observable = this.deviceProfileService.getDeviceProfileNames(false,{ignoreLoading: true}).pipe( + map(subTypes => subTypes.map(subType => subType.name)) + ); + break; + case EntityType.EDGE: + observable = this.edgeService.getEdgeTypes({ignoreLoading: true}).pipe( + map(subTypes => subTypes.map(subType => subType.type)) + ); + break; + case EntityType.ENTITY_VIEW: + observable = this.entityViewService.getEntityViewTypes({ignoreLoading: true}).pipe( + map(subTypes => subTypes.map(subType => subType.type)) + ); + break; + } + return observable; + } } diff --git a/ui-ngx/src/app/shared/components/entity/entity-subtype-autocomplete.component.ts b/ui-ngx/src/app/shared/components/entity/entity-subtype-autocomplete.component.ts index d9c6bf0a6c..dddfe5fe4b 100644 --- a/ui-ngx/src/app/shared/components/entity/entity-subtype-autocomplete.component.ts +++ b/ui-ngx/src/app/shared/components/entity/entity-subtype-autocomplete.component.ts @@ -16,29 +16,28 @@ import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { ControlValueAccessor, UntypedFormBuilder, UntypedFormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; -import { Observable, of, Subscription, throwError } from 'rxjs'; +import { Observable, of, ReplaySubject, Subscription, throwError } from 'rxjs'; import { catchError, debounceTime, distinctUntilChanged, map, - publishReplay, - refCount, switchMap, - tap + tap, + share, } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { AppState } from '@app/core/core.state'; import { TranslateService } from '@ngx-translate/core'; import { DeviceProfileService } from '@core/http/device-profile.service'; -import { EntitySubtype, EntityType } from '@app/shared/models/entity-type.models'; +import { EntityType } from '@app/shared/models/entity-type.models'; import { BroadcastService } from '@app/core/services/broadcast.service'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { AssetProfileService } from '@core/http/asset-profile.service'; import { EntityViewService } from '@core/http/entity-view.service'; import { EdgeService } from '@core/http/edge.service'; import { MatFormFieldAppearance } from '@angular/material/form-field'; -import { EntityInfoData } from '@shared/models/entity.models'; +import { EntityService } from '@core/http/entity.service'; @Component({ selector: 'tb-entity-subtype-autocomplete', @@ -105,7 +104,8 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, private assetProfileService: AssetProfileService, private edgeService: EdgeService, private entityViewService: EntityViewService, - private fb: UntypedFormBuilder) { + private fb: UntypedFormBuilder, + private entityService: EntityService) { this.subTypeFormGroup = this.fb.group({ subType: [null, Validators.maxLength(255)] }); @@ -230,35 +230,22 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, getSubTypes(): Observable> { if (!this.subTypes) { - let subTypesObservable: Observable>; - switch (this.entityType) { - case EntityType.ASSET: - subTypesObservable = this.assetProfileService.getAssetProfileNames(false, {ignoreLoading: true}); - break; - case EntityType.DEVICE: - subTypesObservable = this.deviceProfileService.getDeviceProfileNames(false,{ignoreLoading: true}); - break; - case EntityType.EDGE: - subTypesObservable = this.edgeService.getEdgeTypes({ignoreLoading: true}); - break; - case EntityType.ENTITY_VIEW: - subTypesObservable = this.entityViewService.getEntityViewTypes({ignoreLoading: true}); - break; - } + const subTypesObservable = this.entityService.getEntitySubtypesObservable(this.entityType); if (subTypesObservable) { const excludeSubTypesSet = new Set(this.excludeSubTypes); this.subTypes = subTypesObservable.pipe( - catchError(() => of([] as Array)), + catchError(() => of([] as Array)), map(subTypes => { const filteredSubTypes: Array = []; - subTypes.forEach(subType => { - const typeName = this.isEntitySubType(subType) ? subType.type : subType.name; - return !excludeSubTypesSet.has(typeName) && filteredSubTypes.push(typeName); - }); + subTypes.forEach(subType => !excludeSubTypesSet.has(subType) && filteredSubTypes.push(subType)); return filteredSubTypes; }), - publishReplay(1), - refCount() + share({ + connector: () => new ReplaySubject(1), + resetOnError: false, + resetOnComplete: false, + resetOnRefCountZero: false, + }) ); } else { return throwError(null); @@ -267,10 +254,6 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, return this.subTypes; } - private isEntitySubType(object: EntitySubtype | EntityInfoData): object is EntitySubtype { - return 'type' in object; - } - clear() { this.subTypeFormGroup.get('subType').patchValue(null, {emitEvent: true}); setTimeout(() => { diff --git a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts index fe843e77fc..234f3c7e83 100644 --- a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts +++ b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts @@ -34,7 +34,7 @@ import { coerceArray, coerceBoolean } from '@shared/decorators/coercion'; import { PageLink } from '@shared/models/page/page-link'; import { PageData } from '@shared/models/page/page-data'; import { UtilsService } from '@core/services/utils.service'; -import { EntityInfoData } from '@shared/models/entity.models'; +import { EntityService } from '@core/http/entity.service'; @Component({ selector: 'tb-entity-subtype-list', @@ -132,7 +132,8 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, private entityViewService: EntityViewService, private alarmService: AlarmService, private utils: UtilsService, - private fb: FormBuilder) { + private fb: FormBuilder, + private entityService: EntityService) { this.entitySubtypeListFormGroup = this.fb.group({ entitySubtypeList: [this.entitySubtypeList, this.required ? [Validators.required] : []], entitySubtype: [null] @@ -327,24 +328,9 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, } } if (!this.entitySubtypes) { - let subTypesObservable: Observable>; - switch (this.entityType) { - case EntityType.ASSET: - subTypesObservable = this.assetProfileService.getAssetProfileNames(false, {ignoreLoading: true}); - break; - case EntityType.DEVICE: - subTypesObservable = this.deviceProfileService.getDeviceProfileNames(false,{ignoreLoading: true}); - break; - case EntityType.EDGE: - subTypesObservable = this.edgeService.getEdgeTypes({ignoreLoading: true}); - break; - case EntityType.ENTITY_VIEW: - subTypesObservable = this.entityViewService.getEntityViewTypes({ignoreLoading: true}); - break; - } + const subTypesObservable = this.entityService.getEntitySubtypesObservable(this.entityType); if (subTypesObservable) { this.entitySubtypes = subTypesObservable.pipe( - map(subTypes => subTypes.map(subType => this.isEntitySubType(subType) ? subType.type : subType.name)), share({ connector: () => new ReplaySubject(1), resetOnError: false, @@ -359,10 +345,6 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, return this.entitySubtypes; } - private isEntitySubType(object: EntitySubtype | EntityInfoData): object is EntitySubtype { - return 'type' in object; - } - onFocus() { if (this.dirty) { this.entitySubtypeListFormGroup.get('entitySubtype').updateValueAndValidity({onlySelf: true, emitEvent: true}); diff --git a/ui-ngx/src/app/shared/components/entity/entity-subtype-select.component.ts b/ui-ngx/src/app/shared/components/entity/entity-subtype-select.component.ts index eb2230860d..5da0c9ff4b 100644 --- a/ui-ngx/src/app/shared/components/entity/entity-subtype-select.component.ts +++ b/ui-ngx/src/app/shared/components/entity/entity-subtype-select.component.ts @@ -17,18 +17,19 @@ import { AfterViewInit, Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; import { ControlValueAccessor, UntypedFormBuilder, UntypedFormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; import { Observable, Subject, Subscription, throwError } from 'rxjs'; -import { map, mergeMap, publishReplay, refCount, startWith, tap } from 'rxjs/operators'; +import { map, mergeMap, startWith, tap, share } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { AppState } from '@app/core/core.state'; import { TranslateService } from '@ngx-translate/core'; import { DeviceProfileService } from '@core/http/device-profile.service'; -import { EntitySubtype, EntityType } from '@app/shared/models/entity-type.models'; +import { EntityType } from '@app/shared/models/entity-type.models'; import { BroadcastService } from '@app/core/services/broadcast.service'; import { AssetProfileService } from '@core/http/asset-profile.service'; import { EdgeService } from '@core/http/edge.service'; import { EntityViewService } from '@core/http/entity-view.service'; import { SubscriptSizing } from '@angular/material/form-field'; -import { EntityInfoData } from '@shared/models/entity.models'; +import { isNotEmptyStr } from '@core/utils'; +import { EntityService } from '@core/http/entity.service'; @Component({ selector: 'tb-entity-subtype-select', @@ -67,11 +68,11 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni entitySubtypeTitle: string; entitySubtypeRequiredText: string; - subTypesOptions: Observable>; + subTypesOptions: Observable>; private subTypesOptionsSubject: Subject = new Subject(); - subTypes: Observable>; + private subTypes: Observable>; subTypesLoaded = false; @@ -86,7 +87,8 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni private assetProfileService: AssetProfileService, private edgeService: EdgeService, private entityViewService: EntityViewService, - private fb: UntypedFormBuilder) { + private fb: UntypedFormBuilder, + private entityService: EntityService) { this.subTypeFormGroup = this.fb.group({ subType: [''] }); @@ -137,7 +139,7 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni } this.subTypesOptions = this.subTypesOptionsSubject.asObservable().pipe( - startWith(''), + startWith(''), mergeMap(() => this.getSubTypes()) ); @@ -147,7 +149,7 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni if (!value || value === '') { modelValue = ''; } else { - modelValue = value.type; + modelValue = value; } this.updateView(modelValue); } @@ -194,70 +196,41 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni } } - displaySubTypeFn(subType?: EntitySubtype | string | EntityInfoData): string | undefined { - if (subType && typeof subType !== 'string') { - const typeName = this.isEntitySubType(subType) ? subType.type : subType.name; + displaySubTypeFn(subType?: string): string | undefined { + if (isNotEmptyStr(subType)) { if (this.typeTranslatePrefix) { - return this.translate.instant(this.typeTranslatePrefix + '.' + typeName); + return this.translate.instant(this.typeTranslatePrefix + '.' + subType); } else { - return typeName; + return subType; } } else { return this.translate.instant('entity.all-subtypes'); } } - findSubTypes(searchText: string): Observable> { + findSubTypes(searchText: string): Observable> { return this.getSubTypes().pipe( - map(subTypes => subTypes.filter( subType => { - if (typeof subType === 'string') { - return false; - } else { - return this.isEntitySubType(subType) ? subType.type : subType.name === searchText; - } - })) + map(subTypes => subTypes.filter( subType => subType === searchText)) ); } - getSubTypes(): Observable> { + getSubTypes(): Observable> { if (!this.subTypes) { - switch (this.entityType) { - case EntityType.ASSET: - this.subTypes = this.assetProfileService.getAssetProfileNames(false, {ignoreLoading: true}); - break; - case EntityType.DEVICE: - this.subTypes = this.deviceProfileService.getDeviceProfileNames(false, {ignoreLoading: true}); - break; - case EntityType.EDGE: - this.subTypes = this.edgeService.getEdgeTypes({ignoreLoading: true}); - break; - case EntityType.ENTITY_VIEW: - this.subTypes = this.entityViewService.getEntityViewTypes({ignoreLoading: true}); - break; - } - if (this.subTypes) { - this.subTypes = this.subTypes.pipe( - map((allSubtypes) => { - allSubtypes.unshift(''); - this.subTypesLoaded = true; - return allSubtypes; + const subTypesObservable = this.entityService.getEntitySubtypesObservable(this.entityType); + if (subTypesObservable) { + this.subTypes = subTypesObservable.pipe( + map((subTypes) => { + this.subTypesLoaded = true; + subTypes.unshift(''); + return subTypes; }), tap((subTypes) => { - const type: EntitySubtype | string = this.subTypeFormGroup.get('subType').value; - const strType = typeof type === 'string' ? type : type.type; - const found = subTypes.find((subType) => { - if (typeof subType === 'string') { - return subType === type; - } else { - return this.isEntitySubType(subType) ? subType.type : subType.name === strType; - } - }); + const found = subTypes.find(subType => subType === this.subTypeFormGroup.get('subType').value); if (found) { this.subTypeFormGroup.get('subType').patchValue(found); } }), - publishReplay(1), - refCount() + share() ); } else { return throwError(null); @@ -265,8 +238,4 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni } return this.subTypes; } - - private isEntitySubType(object: EntitySubtype | EntityInfoData): object is EntitySubtype { - return 'type' in object; - } }