UI: added getAssetProfileNames and getDeviceProfileNames APIs

This commit is contained in:
rusikv 2024-01-03 15:18:18 +02:00
parent c43a265868
commit b044c661d3
5 changed files with 75 additions and 33 deletions

View File

@ -21,6 +21,8 @@ import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { PageData } from '@shared/models/page/page-data'; import { PageData } from '@shared/models/page/page-data';
import { AssetProfile, AssetProfileInfo } from '@shared/models/asset.models'; import { AssetProfile, AssetProfileInfo } from '@shared/models/asset.models';
import { EntityInfoData } from '@shared/models/entity.models';
import { isDefinedAndNotNull } from '@core/utils';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -68,4 +70,12 @@ export class AssetProfileService {
return this.http.get<PageData<AssetProfileInfo>>(`/api/assetProfileInfos${pageLink.toQuery()}`, defaultHttpOptionsFromConfig(config)); return this.http.get<PageData<AssetProfileInfo>>(`/api/assetProfileInfos${pageLink.toQuery()}`, defaultHttpOptionsFromConfig(config));
} }
public getAssetProfileNames(activeOnly: boolean = false, config?: RequestConfig): Observable<Array<EntityInfoData>> {
let url = '/api/assetProfile/names';
if (isDefinedAndNotNull(activeOnly)) {
url += `?activeOnly=${activeOnly}`;
}
return this.http.get<Array<EntityInfoData>>(url, defaultHttpOptionsFromConfig(config));
}
} }

View File

@ -31,6 +31,7 @@ import { SortOrder } from '@shared/models/page/sort-order';
import { OtaPackageService } from '@core/http/ota-package.service'; import { OtaPackageService } from '@core/http/ota-package.service';
import { map, mergeMap, tap } from 'rxjs/operators'; import { map, mergeMap, tap } from 'rxjs/operators';
import { Lwm2mSecurityType } from '@shared/models/lwm2m-security-config.models'; import { Lwm2mSecurityType } from '@shared/models/lwm2m-security-config.models';
import { EntityInfoData } from '@shared/models/entity.models';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -169,4 +170,12 @@ export class DeviceProfileService {
return this.http.get<Array<string>>(url, defaultHttpOptionsFromConfig(config)); return this.http.get<Array<string>>(url, defaultHttpOptionsFromConfig(config));
} }
public getDeviceProfileNames(activeOnly: boolean = false, config?: RequestConfig): Observable<Array<EntityInfoData>> {
let url = '/api/deviceProfile/names';
if (isDefinedAndNotNull(activeOnly)) {
url += `?activeOnly=${activeOnly}`;
}
return this.http.get<Array<EntityInfoData>>(url, defaultHttpOptionsFromConfig(config));
}
} }

View File

@ -30,14 +30,15 @@ import {
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@app/core/core.state'; import { AppState } from '@app/core/core.state';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { DeviceService } from '@core/http/device.service'; import { DeviceProfileService } from '@core/http/device-profile.service';
import { EntitySubtype, EntityType } from '@app/shared/models/entity-type.models'; import { EntitySubtype, EntityType } from '@app/shared/models/entity-type.models';
import { BroadcastService } from '@app/core/services/broadcast.service'; import { BroadcastService } from '@app/core/services/broadcast.service';
import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { AssetService } from '@core/http/asset.service'; import { AssetProfileService } from '@core/http/asset-profile.service';
import { EntityViewService } from '@core/http/entity-view.service'; import { EntityViewService } from '@core/http/entity-view.service';
import { EdgeService } from '@core/http/edge.service'; import { EdgeService } from '@core/http/edge.service';
import { MatFormFieldAppearance } from '@angular/material/form-field'; import { MatFormFieldAppearance } from '@angular/material/form-field';
import { EntityInfoData } from '@shared/models/entity.models';
@Component({ @Component({
selector: 'tb-entity-subtype-autocomplete', selector: 'tb-entity-subtype-autocomplete',
@ -100,8 +101,8 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor,
constructor(private store: Store<AppState>, constructor(private store: Store<AppState>,
private broadcast: BroadcastService, private broadcast: BroadcastService,
public translate: TranslateService, public translate: TranslateService,
private deviceService: DeviceService, private deviceProfileService: DeviceProfileService,
private assetService: AssetService, private assetProfileService: AssetProfileService,
private edgeService: EdgeService, private edgeService: EdgeService,
private entityViewService: EntityViewService, private entityViewService: EntityViewService,
private fb: UntypedFormBuilder) { private fb: UntypedFormBuilder) {
@ -229,13 +230,13 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor,
getSubTypes(): Observable<Array<string>> { getSubTypes(): Observable<Array<string>> {
if (!this.subTypes) { if (!this.subTypes) {
let subTypesObservable: Observable<Array<EntitySubtype>>; let subTypesObservable: Observable<Array<EntitySubtype | EntityInfoData>>;
switch (this.entityType) { switch (this.entityType) {
case EntityType.ASSET: case EntityType.ASSET:
subTypesObservable = this.assetService.getAssetTypes({ignoreLoading: true}); subTypesObservable = this.assetProfileService.getAssetProfileNames(false, {ignoreLoading: true});
break; break;
case EntityType.DEVICE: case EntityType.DEVICE:
subTypesObservable = this.deviceService.getDeviceTypes({ignoreLoading: true}); subTypesObservable = this.deviceProfileService.getDeviceProfileNames(false,{ignoreLoading: true});
break; break;
case EntityType.EDGE: case EntityType.EDGE:
subTypesObservable = this.edgeService.getEdgeTypes({ignoreLoading: true}); subTypesObservable = this.edgeService.getEdgeTypes({ignoreLoading: true});
@ -247,10 +248,13 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor,
if (subTypesObservable) { if (subTypesObservable) {
const excludeSubTypesSet = new Set(this.excludeSubTypes); const excludeSubTypesSet = new Set(this.excludeSubTypes);
this.subTypes = subTypesObservable.pipe( this.subTypes = subTypesObservable.pipe(
catchError(() => of([] as Array<EntitySubtype>)), catchError(() => of([] as Array<EntitySubtype | EntityInfoData>)),
map(subTypes => { map(subTypes => {
const filteredSubTypes: Array<string> = []; const filteredSubTypes: Array<string> = [];
subTypes.forEach(subType => !excludeSubTypesSet.has(subType.type) && filteredSubTypes.push(subType.type)); subTypes.forEach(subType => {
const typeName = this.isEntitySubType(subType) ? subType.type : subType.name;
return !excludeSubTypesSet.has(typeName) && filteredSubTypes.push(typeName);
});
return filteredSubTypes; return filteredSubTypes;
}), }),
publishReplay(1), publishReplay(1),
@ -263,6 +267,10 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor,
return this.subTypes; return this.subTypes;
} }
private isEntitySubType(object: EntitySubtype | EntityInfoData): object is EntitySubtype {
return 'type' in object;
}
clear() { clear() {
this.subTypeFormGroup.get('subType').patchValue(null, {emitEvent: true}); this.subTypeFormGroup.get('subType').patchValue(null, {emitEvent: true});
setTimeout(() => { setTimeout(() => {

View File

@ -22,8 +22,8 @@ import { TranslateService } from '@ngx-translate/core';
import { EntitySubtype, EntityType } from '@shared/models/entity-type.models'; import { EntitySubtype, EntityType } from '@shared/models/entity-type.models';
import { MatAutocomplete, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatAutocomplete, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
import { MatChipGrid, MatChipInputEvent } from '@angular/material/chips'; import { MatChipGrid, MatChipInputEvent } from '@angular/material/chips';
import { AssetService } from '@core/http/asset.service'; import { AssetProfileService } from '@core/http/asset-profile.service';
import { DeviceService } from '@core/http/device.service'; import { DeviceProfileService } from '@core/http/device-profile.service';
import { EdgeService } from '@core/http/edge.service'; import { EdgeService } from '@core/http/edge.service';
import { EntityViewService } from '@core/http/entity-view.service'; import { EntityViewService } from '@core/http/entity-view.service';
import { BroadcastService } from '@core/services/broadcast.service'; import { BroadcastService } from '@core/services/broadcast.service';
@ -34,6 +34,7 @@ import { coerceArray, coerceBoolean } from '@shared/decorators/coercion';
import { PageLink } from '@shared/models/page/page-link'; import { PageLink } from '@shared/models/page/page-link';
import { PageData } from '@shared/models/page/page-data'; import { PageData } from '@shared/models/page/page-data';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { EntityInfoData } from '@shared/models/entity.models';
@Component({ @Component({
selector: 'tb-entity-subtype-list', selector: 'tb-entity-subtype-list',
@ -125,8 +126,8 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit,
constructor(private broadcast: BroadcastService, constructor(private broadcast: BroadcastService,
public translate: TranslateService, public translate: TranslateService,
private assetService: AssetService, private assetProfileService: AssetProfileService,
private deviceService: DeviceService, private deviceProfileService: DeviceProfileService,
private edgeService: EdgeService, private edgeService: EdgeService,
private entityViewService: EntityViewService, private entityViewService: EntityViewService,
private alarmService: AlarmService, private alarmService: AlarmService,
@ -326,13 +327,13 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit,
} }
} }
if (!this.entitySubtypes) { if (!this.entitySubtypes) {
let subTypesObservable: Observable<Array<EntitySubtype>>; let subTypesObservable: Observable<Array<EntitySubtype | EntityInfoData>>;
switch (this.entityType) { switch (this.entityType) {
case EntityType.ASSET: case EntityType.ASSET:
subTypesObservable = this.assetService.getAssetTypes({ignoreLoading: true}); subTypesObservable = this.assetProfileService.getAssetProfileNames(false, {ignoreLoading: true});
break; break;
case EntityType.DEVICE: case EntityType.DEVICE:
subTypesObservable = this.deviceService.getDeviceTypes({ignoreLoading: true}); subTypesObservable = this.deviceProfileService.getDeviceProfileNames(false,{ignoreLoading: true});
break; break;
case EntityType.EDGE: case EntityType.EDGE:
subTypesObservable = this.edgeService.getEdgeTypes({ignoreLoading: true}); subTypesObservable = this.edgeService.getEdgeTypes({ignoreLoading: true});
@ -343,7 +344,7 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit,
} }
if (subTypesObservable) { if (subTypesObservable) {
this.entitySubtypes = subTypesObservable.pipe( this.entitySubtypes = subTypesObservable.pipe(
map(subTypes => subTypes.map(subType => subType.type)), map(subTypes => subTypes.map(subType => this.isEntitySubType(subType) ? subType.type : subType.name)),
share({ share({
connector: () => new ReplaySubject(1), connector: () => new ReplaySubject(1),
resetOnError: false, resetOnError: false,
@ -358,6 +359,10 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit,
return this.entitySubtypes; return this.entitySubtypes;
} }
private isEntitySubType(object: EntitySubtype | EntityInfoData): object is EntitySubtype {
return 'type' in object;
}
onFocus() { onFocus() {
if (this.dirty) { if (this.dirty) {
this.entitySubtypeListFormGroup.get('entitySubtype').updateValueAndValidity({onlySelf: true, emitEvent: true}); this.entitySubtypeListFormGroup.get('entitySubtype').updateValueAndValidity({onlySelf: true, emitEvent: true});

View File

@ -21,13 +21,14 @@ import { map, mergeMap, publishReplay, refCount, startWith, tap } from 'rxjs/ope
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@app/core/core.state'; import { AppState } from '@app/core/core.state';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { DeviceService } from '@core/http/device.service'; import { DeviceProfileService } from '@core/http/device-profile.service';
import { EntitySubtype, EntityType } from '@app/shared/models/entity-type.models'; import { EntitySubtype, EntityType } from '@app/shared/models/entity-type.models';
import { BroadcastService } from '@app/core/services/broadcast.service'; import { BroadcastService } from '@app/core/services/broadcast.service';
import { AssetService } from '@core/http/asset.service'; import { AssetProfileService } from '@core/http/asset-profile.service';
import { EdgeService } from '@core/http/edge.service'; import { EdgeService } from '@core/http/edge.service';
import { EntityViewService } from '@core/http/entity-view.service'; import { EntityViewService } from '@core/http/entity-view.service';
import { SubscriptSizing } from '@angular/material/form-field'; import { SubscriptSizing } from '@angular/material/form-field';
import { EntityInfoData } from '@shared/models/entity.models';
@Component({ @Component({
selector: 'tb-entity-subtype-select', selector: 'tb-entity-subtype-select',
@ -66,11 +67,11 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni
entitySubtypeTitle: string; entitySubtypeTitle: string;
entitySubtypeRequiredText: string; entitySubtypeRequiredText: string;
subTypesOptions: Observable<Array<EntitySubtype | string>>; subTypesOptions: Observable<Array<EntitySubtype | string | EntityInfoData>>;
private subTypesOptionsSubject: Subject<string> = new Subject(); private subTypesOptionsSubject: Subject<string> = new Subject();
subTypes: Observable<Array<EntitySubtype | string>>; subTypes: Observable<Array<EntitySubtype | string | EntityInfoData>>;
subTypesLoaded = false; subTypesLoaded = false;
@ -81,8 +82,8 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni
constructor(private store: Store<AppState>, constructor(private store: Store<AppState>,
private broadcast: BroadcastService, private broadcast: BroadcastService,
public translate: TranslateService, public translate: TranslateService,
private deviceService: DeviceService, private deviceProfileService: DeviceProfileService,
private assetService: AssetService, private assetProfileService: AssetProfileService,
private edgeService: EdgeService, private edgeService: EdgeService,
private entityViewService: EntityViewService, private entityViewService: EntityViewService,
private fb: UntypedFormBuilder) { private fb: UntypedFormBuilder) {
@ -136,7 +137,7 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni
} }
this.subTypesOptions = this.subTypesOptionsSubject.asObservable().pipe( this.subTypesOptions = this.subTypesOptionsSubject.asObservable().pipe(
startWith<string | EntitySubtype>(''), startWith<string | EntitySubtype | EntityInfoData>(''),
mergeMap(() => this.getSubTypes()) mergeMap(() => this.getSubTypes())
); );
@ -193,34 +194,39 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni
} }
} }
displaySubTypeFn(subType?: EntitySubtype | string): string | undefined { displaySubTypeFn(subType?: EntitySubtype | string | EntityInfoData): string | undefined {
if (subType && typeof subType !== 'string') { if (subType && typeof subType !== 'string') {
const typeName = this.isEntitySubType(subType) ? subType.type : subType.name;
if (this.typeTranslatePrefix) { if (this.typeTranslatePrefix) {
return this.translate.instant(this.typeTranslatePrefix + '.' + subType.type); return this.translate.instant(this.typeTranslatePrefix + '.' + typeName);
} else { } else {
return subType.type; return typeName;
} }
} else { } else {
return this.translate.instant('entity.all-subtypes'); return this.translate.instant('entity.all-subtypes');
} }
} }
findSubTypes(searchText?: string): Observable<Array<EntitySubtype | string>> { findSubTypes(searchText: string): Observable<Array<EntitySubtype | string | EntityInfoData>> {
return this.getSubTypes().pipe( return this.getSubTypes().pipe(
map(subTypes => subTypes.filter( subType => { map(subTypes => subTypes.filter( subType => {
return searchText ? (typeof subType === 'string' ? false : subType.type === searchText) : false; if (typeof subType === 'string') {
return false;
} else {
return this.isEntitySubType(subType) ? subType.type : subType.name === searchText;
}
})) }))
); );
} }
getSubTypes(): Observable<Array<EntitySubtype | string>> { getSubTypes(): Observable<Array<EntitySubtype | string | EntityInfoData>> {
if (!this.subTypes) { if (!this.subTypes) {
switch (this.entityType) { switch (this.entityType) {
case EntityType.ASSET: case EntityType.ASSET:
this.subTypes = this.assetService.getAssetTypes({ignoreLoading: true}); this.subTypes = this.assetProfileService.getAssetProfileNames(false, {ignoreLoading: true});
break; break;
case EntityType.DEVICE: case EntityType.DEVICE:
this.subTypes = this.deviceService.getDeviceTypes({ignoreLoading: true}); this.subTypes = this.deviceProfileService.getDeviceProfileNames(false, {ignoreLoading: true});
break; break;
case EntityType.EDGE: case EntityType.EDGE:
this.subTypes = this.edgeService.getEdgeTypes({ignoreLoading: true}); this.subTypes = this.edgeService.getEdgeTypes({ignoreLoading: true});
@ -243,7 +249,7 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni
if (typeof subType === 'string') { if (typeof subType === 'string') {
return subType === type; return subType === type;
} else { } else {
return subType.type === strType; return this.isEntitySubType(subType) ? subType.type : subType.name === strType;
} }
}); });
if (found) { if (found) {
@ -259,4 +265,8 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni
} }
return this.subTypes; return this.subTypes;
} }
private isEntitySubType(object: EntitySubtype | EntityInfoData): object is EntitySubtype {
return 'type' in object;
}
} }