Browse Source

Merge pull request #7780 from ArtemDzhereleiko/AD/form-components/refactoring

Refactoring form array
pull/8278/head
Igor Kulikov 4 years ago
committed by GitHub
parent
commit
f448f6bf79
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html
  2. 59
      ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.ts
  3. 4
      ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.html
  4. 57
      ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.ts
  5. 28
      ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.ts
  6. 4
      ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.html
  7. 54
      ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.ts
  8. 17
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes-key-list.component.ts
  9. 4
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html
  10. 63
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.ts
  11. 10
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-instances.component.ts
  12. 20
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resources.component.ts
  13. 10
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.ts
  14. 4
      ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-communication-config.component.html
  15. 55
      ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-communication-config.component.ts
  16. 4
      ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-mapping.component.html
  17. 59
      ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-mapping.component.ts
  18. 63
      ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts
  19. 8
      ui-ngx/src/app/modules/home/components/relation/relation-filters.component.html
  20. 54
      ui-ngx/src/app/modules/home/components/relation/relation-filters.component.ts
  21. 33
      ui-ngx/src/app/shared/components/kv-map.component.ts

4
ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html

@ -42,7 +42,7 @@
<div class="predicate-list">
<div fxLayout="row" fxLayoutAlign="start" style="height: 71px;"
formArrayName="predicates"
*ngFor="let predicateControl of predicatesFormArray().controls; let $index = index">
*ngFor="let predicateControl of predicatesFormArray.controls; let $index = index">
<div fxFlex="8" fxLayout="row" fxLayoutAlign="center" class="filters-operation">
<span *ngIf="$index > 0">{{ complexOperationTranslations.get(operation) | translate }}</span>
</div>
@ -68,7 +68,7 @@
</div>
</div>
</div>
<span [fxShow]="!predicatesFormArray().length"
<span [fxShow]="!predicatesFormArray.length"
fxLayoutAlign="center center" [ngClass]="{'disabled': disabled}"
class="no-data-found" translate>filter.no-filters</span>
</div>

59
ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component, forwardRef, Inject, Input, OnInit } from '@angular/core';
import { Component, forwardRef, Inject, Input, OnDestroy, OnInit } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
@ -27,7 +27,7 @@ import {
Validator,
Validators
} from '@angular/forms';
import { Observable, of, Subscription } from 'rxjs';
import { Observable, of, Subject } from 'rxjs';
import {
ComplexFilterPredicateInfo,
ComplexOperation,
@ -37,7 +37,7 @@ import {
KeyFilterPredicateInfo
} from '@shared/models/query/query.models';
import { MatDialog } from '@angular/material/dialog';
import { map } from 'rxjs/operators';
import { map, takeUntil } from 'rxjs/operators';
import { ComponentType } from '@angular/cdk/portal';
import { COMPLEX_FILTER_PREDICATE_DIALOG_COMPONENT_TOKEN } from '@home/components/tokens';
import { ComplexFilterPredicateDialogData } from '@home/components/filter/filter-component.models';
@ -59,7 +59,7 @@ import { ComplexFilterPredicateDialogData } from '@home/components/filter/filter
}
]
})
export class FilterPredicateListComponent implements ControlValueAccessor, Validator, OnInit {
export class FilterPredicateListComponent implements ControlValueAccessor, Validator, OnInit, OnDestroy {
@Input() disabled: boolean;
@ -81,22 +81,29 @@ export class FilterPredicateListComponent implements ControlValueAccessor, Valid
complexOperationTranslations = complexOperationTranslationMap;
private destroy$ = new Subject<void>();
private propagateChange = null;
private valueChangeSubscription: Subscription = null;
constructor(private fb: UntypedFormBuilder,
@Inject(COMPLEX_FILTER_PREDICATE_DIALOG_COMPONENT_TOKEN) private complexFilterPredicateDialogComponent: ComponentType<any>,
private dialog: MatDialog) {
}
ngOnInit(): void {
this.filterListFormGroup = this.fb.group({});
this.filterListFormGroup.addControl('predicates',
this.fb.array([]));
this.filterListFormGroup = this.fb.group({
predicates: this.fb.array([])
});
this.filterListFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => this.updateModel());
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
predicatesFormArray(): UntypedFormArray {
get predicatesFormArray(): UntypedFormArray {
return this.filterListFormGroup.get('predicates') as UntypedFormArray;
}
@ -123,28 +130,26 @@ export class FilterPredicateListComponent implements ControlValueAccessor, Valid
}
writeValue(predicates: Array<KeyFilterPredicateInfo>): void {
if (this.valueChangeSubscription) {
this.valueChangeSubscription.unsubscribe();
}
const predicateControls: Array<AbstractControl> = [];
if (predicates) {
for (const predicate of predicates) {
predicateControls.push(this.fb.control(predicate, [Validators.required]));
}
}
this.filterListFormGroup.setControl('predicates', this.fb.array(predicateControls));
this.valueChangeSubscription = this.filterListFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
if (this.disabled) {
this.filterListFormGroup.disable({emitEvent: false});
if (predicates.length === this.predicatesFormArray.length) {
this.predicatesFormArray.patchValue(predicates, {emitEvent: false});
} else {
this.filterListFormGroup.enable({emitEvent: false});
const predicateControls: Array<AbstractControl> = [];
if (predicates) {
for (const predicate of predicates) {
predicateControls.push(this.fb.control(predicate, [Validators.required]));
}
}
this.filterListFormGroup.setControl('predicates', this.fb.array(predicateControls), {emitEvent: false});
if (this.disabled) {
this.filterListFormGroup.disable({emitEvent: false});
} else {
this.filterListFormGroup.enable({emitEvent: false});
}
}
}
public removePredicate(index: number) {
(this.filterListFormGroup.get('predicates') as UntypedFormArray).removeAt(index);
this.predicatesFormArray.removeAt(index);
}
public addPredicate(complex: boolean) {

4
ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.html

@ -36,7 +36,7 @@
<div class="key-filter-list">
<div fxLayout="row" fxLayoutAlign="start" style="max-height: 71px;"
formArrayName="keyFilters"
*ngFor="let keyFilterControl of keyFiltersFormArray().controls; let $index = index">
*ngFor="let keyFilterControl of keyFiltersFormArray.controls; let $index = index">
<div fxFlex="8" class="filters-operation">
<span *ngIf="$index > 0" translate>filter.operation.and</span>
</div>
@ -63,7 +63,7 @@
<mat-divider></mat-divider>
</div>
</div>
<span [fxShow]="!keyFiltersFormArray().length"
<span [fxShow]="!keyFiltersFormArray.length"
fxLayoutAlign="center center" [ngClass]="{'disabled': disabled}"
class="no-data-found" translate>filter.no-key-filters</span>
</div>

57
ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
@ -28,7 +28,7 @@ import {
Validator,
Validators
} from '@angular/forms';
import { Observable, Subscription } from 'rxjs';
import { Observable, Subject } from 'rxjs';
import {
EntityKeyType,
entityKeyTypeTranslationMap,
@ -39,6 +39,7 @@ import { MatDialog } from '@angular/material/dialog';
import { deepClone } from '@core/utils';
import { KeyFilterDialogComponent, KeyFilterDialogData } from '@home/components/filter/key-filter-dialog.component';
import { EntityId } from '@shared/models/id/entity-id';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'tb-key-filter-list',
@ -57,7 +58,7 @@ import { EntityId } from '@shared/models/id/entity-id';
}
]
})
export class KeyFilterListComponent implements ControlValueAccessor, Validator, OnInit {
export class KeyFilterListComponent implements ControlValueAccessor, Validator, OnInit, OnDestroy {
@Input() disabled: boolean;
@ -75,22 +76,30 @@ export class KeyFilterListComponent implements ControlValueAccessor, Validator,
keyFiltersControl: UntypedFormControl;
private destroy$ = new Subject<void>();
private propagateChange = null;
private valueChangeSubscription: Subscription = null;
constructor(private fb: UntypedFormBuilder,
private dialog: MatDialog) {
}
ngOnInit(): void {
this.keyFilterListFormGroup = this.fb.group({});
this.keyFilterListFormGroup.addControl('keyFilters',
this.fb.array([]));
this.keyFilterListFormGroup = this.fb.group({
keyFilters: this.fb.array([])
});
this.keyFiltersControl = this.fb.control(null);
this.keyFilterListFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => this.updateModel());
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
keyFiltersFormArray(): UntypedFormArray {
get keyFiltersFormArray(): UntypedFormArray {
return this.keyFilterListFormGroup.get('keyFilters') as UntypedFormArray;
}
@ -119,23 +128,21 @@ export class KeyFilterListComponent implements ControlValueAccessor, Validator,
}
writeValue(keyFilters: Array<KeyFilterInfo>): void {
if (this.valueChangeSubscription) {
this.valueChangeSubscription.unsubscribe();
}
const keyFilterControls: Array<AbstractControl> = [];
if (keyFilters) {
for (const keyFilter of keyFilters) {
keyFilterControls.push(this.fb.control(keyFilter, [Validators.required]));
}
}
this.keyFilterListFormGroup.setControl('keyFilters', this.fb.array(keyFilterControls));
this.valueChangeSubscription = this.keyFilterListFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
if (this.disabled) {
this.keyFilterListFormGroup.disable({emitEvent: false});
if (keyFilters.length === this.keyFiltersFormArray.length) {
this.keyFiltersFormArray.patchValue(keyFilters, {emitEvent: false});
} else {
this.keyFilterListFormGroup.enable({emitEvent: false});
const keyFilterControls: Array<AbstractControl> = [];
if (keyFilters) {
for (const keyFilter of keyFilters) {
keyFilterControls.push(this.fb.control(keyFilter, [Validators.required]));
}
}
this.keyFilterListFormGroup.setControl('keyFilters', this.fb.array(keyFilterControls), {emitEvent: false});
if (this.disabled) {
this.keyFilterListFormGroup.disable({emitEvent: false});
} else {
this.keyFilterListFormGroup.enable({emitEvent: false});
}
}
const keyFiltersArray = keyFilterInfosToKeyFilters(keyFilters);
this.keyFiltersControl.patchValue(keyFiltersArray, {emitEvent: false});

28
ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
@ -23,15 +23,16 @@ import {
UntypedFormControl,
UntypedFormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR, ValidationErrors,
NG_VALUE_ACCESSOR,
Validator,
Validators
} from '@angular/forms';
import { DeviceProfileAlarmRule, alarmRuleValidator } from '@shared/models/device.models';
import { MatDialog } from '@angular/material/dialog';
import { Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { AlarmSeverity, alarmSeverityTranslations } from '@shared/models/alarm.models';
import { EntityId } from '@shared/models/id/entity-id';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'tb-create-alarm-rules',
@ -50,7 +51,7 @@ import { EntityId } from '@shared/models/id/entity-id';
}
]
})
export class CreateAlarmRulesComponent implements ControlValueAccessor, OnInit, Validator {
export class CreateAlarmRulesComponent implements ControlValueAccessor, OnInit, Validator, OnDestroy {
alarmSeverities = Object.keys(AlarmSeverity);
alarmSeverityEnum = AlarmSeverity;
@ -67,8 +68,7 @@ export class CreateAlarmRulesComponent implements ControlValueAccessor, OnInit,
private usedSeverities: AlarmSeverity[] = [];
private valueChangeSubscription: Subscription = null;
private destroy$ = new Subject<void>();
private propagateChange = (v: any) => { };
constructor(private dialog: MatDialog,
@ -86,6 +86,14 @@ export class CreateAlarmRulesComponent implements ControlValueAccessor, OnInit,
this.createAlarmRulesFormGroup = this.fb.group({
createAlarmRules: this.fb.array([])
});
this.createAlarmRulesFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => this.updateModel());
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
createAlarmRulesFormArray(): UntypedFormArray {
@ -102,9 +110,6 @@ export class CreateAlarmRulesComponent implements ControlValueAccessor, OnInit,
}
writeValue(createAlarmRules: {[severity: string]: DeviceProfileAlarmRule}): void {
if (this.valueChangeSubscription) {
this.valueChangeSubscription.unsubscribe();
}
const createAlarmRulesControls: Array<AbstractControl> = [];
if (createAlarmRules) {
Object.keys(createAlarmRules).forEach((severity) => {
@ -118,15 +123,12 @@ export class CreateAlarmRulesComponent implements ControlValueAccessor, OnInit,
}));
});
}
this.createAlarmRulesFormGroup.setControl('createAlarmRules', this.fb.array(createAlarmRulesControls));
this.createAlarmRulesFormGroup.setControl('createAlarmRules', this.fb.array(createAlarmRulesControls), {emitEvent: false});
if (this.disabled) {
this.createAlarmRulesFormGroup.disable({emitEvent: false});
} else {
this.createAlarmRulesFormGroup.enable({emitEvent: false});
}
this.valueChangeSubscription = this.createAlarmRulesFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
this.updateUsedSeverities();
if (!this.disabled && !this.createAlarmRulesFormGroup.valid) {
this.updateModel();

4
ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.html

@ -17,7 +17,7 @@
-->
<div fxLayout="column">
<div class="tb-device-profile-alarms">
<div *ngFor="let alarmControl of alarmsFormArray().controls; trackBy: trackByAlarm;
<div *ngFor="let alarmControl of alarmsFormArray.controls; trackBy: trackByAlarm;
let $index = index; last as isLast;"
fxLayout="column" [ngStyle]="!isLast ? {paddingBottom: '8px'} : {}">
<tb-device-profile-alarm [formControl]="alarmControl"
@ -27,7 +27,7 @@
</tb-device-profile-alarm>
</div>
</div>
<div *ngIf="!alarmsFormArray().controls.length">
<div *ngIf="!alarmsFormArray.controls.length">
<span translate fxLayoutAlign="center center"
class="tb-prompt">device-profile.no-alarm-rules</span>
</div>

54
ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
@ -32,9 +32,9 @@ import { AppState } from '@app/core/core.state';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { DeviceProfileAlarm, deviceProfileAlarmValidator } from '@shared/models/device.models';
import { guid } from '@core/utils';
import { Subscription } from 'rxjs';
import { MatDialog } from '@angular/material/dialog';
import { Subject } from 'rxjs';
import { EntityId } from '@shared/models/id/entity-id';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'tb-device-profile-alarms',
@ -53,7 +53,7 @@ import { EntityId } from '@shared/models/id/entity-id';
}
]
})
export class DeviceProfileAlarmsComponent implements ControlValueAccessor, OnInit, Validator {
export class DeviceProfileAlarmsComponent implements ControlValueAccessor, OnInit, Validator, OnDestroy {
deviceProfileAlarmsFormGroup: UntypedFormGroup;
@ -72,13 +72,11 @@ export class DeviceProfileAlarmsComponent implements ControlValueAccessor, OnIni
@Input()
deviceProfileId: EntityId;
private valueChangeSubscription: Subscription = null;
private destroy$ = new Subject<void>();
private propagateChange = (v: any) => { };
constructor(private store: Store<AppState>,
private fb: UntypedFormBuilder,
private dialog: MatDialog) {
private fb: UntypedFormBuilder) {
}
registerOnChange(fn: any): void {
@ -92,9 +90,17 @@ export class DeviceProfileAlarmsComponent implements ControlValueAccessor, OnIni
this.deviceProfileAlarmsFormGroup = this.fb.group({
alarms: this.fb.array([])
});
this.deviceProfileAlarmsFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => this.updateModel());
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
alarmsFormArray(): UntypedFormArray {
get alarmsFormArray(): UntypedFormArray {
return this.deviceProfileAlarmsFormGroup.get('alarms') as UntypedFormArray;
}
@ -108,24 +114,22 @@ export class DeviceProfileAlarmsComponent implements ControlValueAccessor, OnIni
}
writeValue(alarms: Array<DeviceProfileAlarm> | null): void {
if (this.valueChangeSubscription) {
this.valueChangeSubscription.unsubscribe();
}
const alarmsControls: Array<AbstractControl> = [];
if (alarms) {
alarms.forEach((alarm) => {
alarmsControls.push(this.fb.control(alarm, [Validators.required]));
});
}
this.deviceProfileAlarmsFormGroup.setControl('alarms', this.fb.array(alarmsControls));
if (this.disabled) {
this.deviceProfileAlarmsFormGroup.disable({emitEvent: false});
if (alarms?.length === this.alarmsFormArray.length) {
this.alarmsFormArray.patchValue(alarms, {emitEvent: false});
} else {
this.deviceProfileAlarmsFormGroup.enable({emitEvent: false});
const alarmsControls: Array<AbstractControl> = [];
if (alarms) {
alarms.forEach((alarm) => {
alarmsControls.push(this.fb.control(alarm, [Validators.required]));
});
}
this.deviceProfileAlarmsFormGroup.setControl('alarms', this.fb.array(alarmsControls), {emitEvent: false});
if (this.disabled) {
this.deviceProfileAlarmsFormGroup.disable({emitEvent: false});
} else {
this.deviceProfileAlarmsFormGroup.enable({emitEvent: false});
}
}
this.valueChangeSubscription = this.deviceProfileAlarmsFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
}
public trackByAlarm(index: number, alarmControl: AbstractControl): string {

17
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-attributes-key-list.component.ts

@ -26,7 +26,7 @@ import {
Validator,
Validators
} from '@angular/forms';
import { Subject, Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import {
AttributeName,
AttributeNameTranslationMap,
@ -70,7 +70,6 @@ export class Lwm2mAttributesKeyListComponent extends PageComponent implements Co
attributesValueFormGroup: UntypedFormGroup;
private propagateChange = null;
private valueChange$: Subscription = null;
private destroy$ = new Subject<void>();
private usedAttributesName: AttributeName[] = [];
@ -80,6 +79,9 @@ export class Lwm2mAttributesKeyListComponent extends PageComponent implements Co
this.attributesValueFormGroup = this.fb.group({
attributesValue: this.fb.array([])
});
this.attributesValueFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => this.updateModel());
}
ngOnInit() {
@ -92,9 +94,6 @@ export class Lwm2mAttributesKeyListComponent extends PageComponent implements Co
}
ngOnDestroy() {
if (this.valueChange$) {
this.valueChange$.unsubscribe();
}
this.destroy$.next();
this.destroy$.complete();
}
@ -116,24 +115,18 @@ export class Lwm2mAttributesKeyListComponent extends PageComponent implements Co
}
writeValue(keyValMap: AttributesNameValueMap): void {
if (this.valueChange$) {
this.valueChange$.unsubscribe();
}
const attributesValueControls: Array<AbstractControl> = [];
if (keyValMap) {
(Object.keys(keyValMap) as AttributeName[]).forEach(name => {
attributesValueControls.push(this.createdFormGroup({name, value: keyValMap[name]}));
});
}
this.attributesValueFormGroup.setControl('attributesValue', this.fb.array(attributesValueControls));
this.attributesValueFormGroup.setControl('attributesValue', this.fb.array(attributesValueControls), {emitEvent: false});
if (this.disabled) {
this.attributesValueFormGroup.disable({emitEvent: false});
} else {
this.attributesValueFormGroup.enable({emitEvent: false});
}
this.valueChange$ = this.attributesValueFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
this.updateUsedAttributesName();
}

4
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html

@ -17,7 +17,7 @@
-->
<div fxLayout="column">
<mat-accordion multi="true">
<div *ngFor="let serverConfig of serverConfigsFromArray().controls; trackBy: trackByParams; let $index = index;">
<div *ngFor="let serverConfig of serverConfigsFromArray.controls; trackBy: trackByParams; let $index = index;">
<tb-profile-lwm2m-device-config-server
[formControl]="serverConfig"
(removeServer)="removeServerConfig($event, $index)"
@ -25,7 +25,7 @@
</tb-profile-lwm2m-device-config-server>
</div>
</mat-accordion>
<div *ngIf="!serverConfigsFromArray().controls.length" style="margin:32px 0">
<div *ngIf="!serverConfigsFromArray.controls.length" style="margin:32px 0">
<span translate fxLayoutAlign="center center"
class="tb-prompt">device-profile.lwm2m.no-config-servers</span>
</div>

63
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, forwardRef, Input, OnDestroy, OnInit, Output } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
@ -24,13 +24,13 @@ import {
NG_VALIDATORS,
NG_VALUE_ACCESSOR
} from '@angular/forms';
import { of, Subscription } from 'rxjs';
import { of, Subject } from 'rxjs';
import { ServerSecurityConfig } from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models';
import { TranslateService } from '@ngx-translate/core';
import { DialogService } from '@core/services/dialog.service';
import { MatDialog } from '@angular/material/dialog';
import { Lwm2mBootstrapAddConfigServerDialogComponent } from '@home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component';
import { mergeMap } from 'rxjs/operators';
import { mergeMap, takeUntil } from 'rxjs/operators';
import { DeviceProfileService } from '@core/http/device-profile.service';
import { Lwm2mSecurityType } from '@shared/models/lwm2m-security-config.models';
@ -50,7 +50,7 @@ import { Lwm2mSecurityType } from '@shared/models/lwm2m-security-config.models';
}
]
})
export class Lwm2mBootstrapConfigServersComponent implements OnInit, ControlValueAccessor {
export class Lwm2mBootstrapConfigServersComponent implements OnInit, ControlValueAccessor, OnDestroy {
bootstrapConfigServersFormGroup: UntypedFormGroup;
@ -72,8 +72,7 @@ export class Lwm2mBootstrapConfigServersComponent implements OnInit, ControlValu
}
}
private valueChangeSubscription: Subscription = null;
private destroy$ = new Subject<void>();
private propagateChange = (v: any) => { };
constructor(public translate: TranslateService,
@ -94,9 +93,17 @@ export class Lwm2mBootstrapConfigServersComponent implements OnInit, ControlValu
this.bootstrapConfigServersFormGroup = this.fb.group({
serverConfigs: this.fb.array([])
});
this.bootstrapConfigServersFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => this.updateModel());
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
serverConfigsFromArray(): UntypedFormArray {
get serverConfigsFromArray(): UntypedFormArray {
return this.bootstrapConfigServersFormGroup.get('serverConfigs') as UntypedFormArray;
}
@ -110,24 +117,22 @@ export class Lwm2mBootstrapConfigServersComponent implements OnInit, ControlValu
}
writeValue(serverConfigs: Array<ServerSecurityConfig> | null): void {
if (this.valueChangeSubscription) {
this.valueChangeSubscription.unsubscribe();
}
const serverConfigsControls: Array<AbstractControl> = [];
if (serverConfigs) {
serverConfigs.forEach((serverConfig) => {
serverConfigsControls.push(this.fb.control(serverConfig));
});
}
this.bootstrapConfigServersFormGroup.setControl('serverConfigs', this.fb.array(serverConfigsControls));
if (this.disabled) {
this.bootstrapConfigServersFormGroup.disable({emitEvent: false});
if (serverConfigs?.length === this.serverConfigsFromArray.length) {
this.serverConfigsFromArray.patchValue(serverConfigs, {emitEvent: false});
} else {
this.bootstrapConfigServersFormGroup.enable({emitEvent: false});
const serverConfigsControls: Array<AbstractControl> = [];
if (serverConfigs) {
serverConfigs.forEach((serverConfig) => {
serverConfigsControls.push(this.fb.control(serverConfig));
});
}
this.bootstrapConfigServersFormGroup.setControl('serverConfigs', this.fb.array(serverConfigsControls), {emitEvent: false});
if (this.disabled) {
this.bootstrapConfigServersFormGroup.disable({emitEvent: false});
} else {
this.bootstrapConfigServersFormGroup.enable({emitEvent: false});
}
}
this.valueChangeSubscription = this.bootstrapConfigServersFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
}
trackByParams(index: number): number {
@ -147,7 +152,7 @@ export class Lwm2mBootstrapConfigServersComponent implements OnInit, ControlValu
true
).subscribe((result) => {
if (result) {
this.serverConfigsFromArray().removeAt(index);
this.serverConfigsFromArray.removeAt(index);
}
});
}
@ -169,7 +174,7 @@ export class Lwm2mBootstrapConfigServersComponent implements OnInit, ControlValu
addServerConfigObs.subscribe((serverConfig) => {
if (serverConfig) {
serverConfig.securityMode = Lwm2mSecurityType.NO_SEC;
this.serverConfigsFromArray().push(this.fb.control(serverConfig));
this.serverConfigsFromArray.push(this.fb.control(serverConfig));
this.updateModel();
} else {
this.isTransportWasRunWithBootstrap = false;
@ -196,7 +201,7 @@ export class Lwm2mBootstrapConfigServersComponent implements OnInit, ControlValu
}
private isBootstrapAdded(): boolean {
const serverConfigsArray = this.serverConfigsFromArray().getRawValue();
const serverConfigsArray = this.serverConfigsFromArray.getRawValue();
for (let i = 0; i < serverConfigsArray.length; i++) {
if (serverConfigsArray[i].bootstrapServerIs) {
return true;
@ -207,15 +212,15 @@ export class Lwm2mBootstrapConfigServersComponent implements OnInit, ControlValu
private removeBootstrapServerConfig(): void {
if (this.bootstrapConfigServersFormGroup) {
const bootstrapServerIndex = this.serverConfigsFromArray().getRawValue().findIndex(server => server.bootstrapServerIs === true);
const bootstrapServerIndex = this.serverConfigsFromArray.getRawValue().findIndex(server => server.bootstrapServerIs === true);
if (bootstrapServerIndex !== -1) {
this.serverConfigsFromArray().removeAt(bootstrapServerIndex);
this.serverConfigsFromArray.removeAt(bootstrapServerIndex);
}
}
}
private updateModel() {
const serverConfigs: Array<ServerSecurityConfig> = this.serverConfigsFromArray().value;
const serverConfigs: Array<ServerSecurityConfig> = this.serverConfigsFromArray.value;
this.propagateChange(serverConfigs);
}
}

10
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-instances.component.ts

@ -80,6 +80,8 @@ export class Lwm2mObserveAttrTelemetryInstancesComponent implements ControlValue
this.instancesFormGroup = this.fb.group({
instances: this.fb.array([])
});
this.valueChange$ = this.instancesFormGroup.valueChanges.subscribe(value => this.updateModel(value.instances));
}
ngOnDestroy() {
@ -122,22 +124,16 @@ export class Lwm2mObserveAttrTelemetryInstancesComponent implements ControlValue
if (instances.length === this.instancesFormArray.length) {
this.instancesFormArray.patchValue(instances, {emitEvent: false});
} else {
if (this.valueChange$) {
this.valueChange$.unsubscribe();
}
const instancesControl: Array<AbstractControl> = [];
if (instances) {
instances.forEach((instance) => {
instancesControl.push(this.createInstanceFormGroup(instance));
});
}
this.instancesFormGroup.setControl('instances', this.fb.array(instancesControl));
this.instancesFormGroup.setControl('instances', this.fb.array(instancesControl), {emitEvent: false});
if (this.disabled) {
this.instancesFormGroup.disable({emitEvent: false});
}
this.valueChange$ = this.instancesFormGroup.valueChanges.subscribe(value => {
this.updateModel(value.instances);
});
}
}

20
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry-resources.component.ts

@ -29,7 +29,7 @@ import {
} from '@angular/forms';
import { ResourceLwM2M } from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { combineLatest, Subject, Subscription } from 'rxjs';
import { combineLatest, Subject } from 'rxjs';
import { startWith, takeUntil } from 'rxjs/operators';
@Component({
@ -71,19 +71,19 @@ export class Lwm2mObserveAttrTelemetryResourcesComponent implements ControlValue
}
private destroy$ = new Subject<void>();
private valueChange$: Subscription = null;
private propagateChange = (v: any) => { };
constructor(private fb: UntypedFormBuilder) {
this.resourcesFormGroup = this.fb.group({
resources: this.fb.array([])
});
this.resourcesFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => this.updateModel(this.resourcesFormGroup.getRawValue().resources));
}
ngOnDestroy() {
if (this.valueChange$) {
this.valueChange$.unsubscribe();
}
this.destroy$.next();
this.destroy$.complete();
}
@ -131,24 +131,18 @@ export class Lwm2mObserveAttrTelemetryResourcesComponent implements ControlValue
private updatedResources(resources: ResourceLwM2M[]): void {
if (resources.length === this.resourcesFormArray.length) {
this.resourcesFormArray.patchValue(resources, {onlySelf: true});
this.resourcesFormArray.patchValue(resources, {onlySelf: true, emitEvent: false});
} else {
if (this.valueChange$) {
this.valueChange$.unsubscribe();
}
const resourcesControl: Array<AbstractControl> = [];
if (resources) {
resources.forEach((resource) => {
resourcesControl.push(this.createdResourceFormGroup(resource));
});
}
this.resourcesFormGroup.setControl('resources', this.fb.array(resourcesControl));
this.resourcesFormGroup.setControl('resources', this.fb.array(resourcesControl), {emitEvent: false});
if (this.disabled) {
this.resourcesFormGroup.disable({emitEvent: false});
}
this.valueChange$ = this.resourcesFormGroup.valueChanges.subscribe(() => {
this.updateModel(this.resourcesFormGroup.getRawValue().resources);
});
}
}

10
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-observe-attr-telemetry.component.ts

@ -86,6 +86,8 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor,
this.modelsFormGroup = this.fb.group({
models: this.fb.array([])
});
this.valueChange$ = this.modelsFormGroup.valueChanges.subscribe(value => this.updateModel(value.models));
}
ngOnDestroy() {
@ -130,20 +132,14 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor,
if (models.length === this.modelsFormArray.length) {
this.modelsFormArray.patchValue(models, {emitEvent: false});
} else {
if (this.valueChange$) {
this.valueChange$.unsubscribe();
}
const modelControls: Array<AbstractControl> = [];
models.forEach(model => {
modelControls.push(this.createModelFormGroup(model));
});
this.modelsFormGroup.setControl('models', this.fb.array(modelControls));
this.modelsFormGroup.setControl('models', this.fb.array(modelControls), {emitEvent: false});
if (this.disabled) {
this.modelsFormGroup.disable({emitEvent: false});
}
this.valueChange$ = this.modelsFormGroup.valueChanges.subscribe(value => {
this.updateModel(value.models);
});
}
}

4
ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-communication-config.component.html

@ -16,7 +16,7 @@
-->
<div fxLayout="column">
<div *ngFor="let deviceProfileCommunication of communicationConfigFormArray().controls; let $index = index;
<div *ngFor="let deviceProfileCommunication of communicationConfigFormArray.controls; let $index = index;
last as isLast;" fxLayout="row" fxLayoutAlign="start center"
fxLayoutGap="8px" class="scope-row" [formGroup]="deviceProfileCommunication">
<div class="communication-config" fxFlex fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start">
@ -58,7 +58,7 @@
<mat-icon>remove_circle_outline</mat-icon>
</button>
</div>
<div *ngIf="!communicationConfigFormArray().controls.length && !disabled">
<div *ngIf="!communicationConfigFormArray.controls.length && !disabled">
<span fxLayoutAlign="center center" class="tb-prompt required required-text" translate>device-profile.snmp.please-add-communication-config</span>
</div>
<div *ngIf="!disabled && isAddEnabled">

55
ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-communication-config.component.ts

@ -27,7 +27,7 @@ import {
Validators
} from '@angular/forms';
import { SnmpCommunicationConfig, SnmpSpecType, SnmpSpecTypeTranslationMap } from '@shared/models/device.models';
import { Subject, Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { isUndefinedOrNull } from '@core/utils';
import { takeUntil } from 'rxjs/operators';
@ -58,7 +58,6 @@ export class SnmpDeviceProfileCommunicationConfigComponent implements OnInit, On
disabled: boolean;
private usedSpecType: SnmpSpecType[] = [];
private valueChange$: Subscription = null;
private destroy$ = new Subject<void>();
private propagateChange = (v: any) => { };
@ -68,17 +67,17 @@ export class SnmpDeviceProfileCommunicationConfigComponent implements OnInit, On
this.deviceProfileCommunicationConfig = this.fb.group({
communicationConfig: this.fb.array([])
});
this.deviceProfileCommunicationConfig.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => this.updateModel());
}
ngOnDestroy() {
if (this.valueChange$) {
this.valueChange$.unsubscribe();
}
this.destroy$.next();
this.destroy$.complete();
}
communicationConfigFormArray(): UntypedFormArray {
get communicationConfigFormArray(): UntypedFormArray {
return this.deviceProfileCommunicationConfig.get('communicationConfig') as UntypedFormArray;
}
@ -99,27 +98,27 @@ export class SnmpDeviceProfileCommunicationConfigComponent implements OnInit, On
}
writeValue(communicationConfig: SnmpCommunicationConfig[]) {
if (this.valueChange$) {
this.valueChange$.unsubscribe();
}
const communicationConfigControl: Array<AbstractControl> = [];
if (communicationConfig) {
communicationConfig.forEach((config) => {
communicationConfigControl.push(this.createdFormGroup(config));
});
}
this.deviceProfileCommunicationConfig.setControl('communicationConfig', this.fb.array(communicationConfigControl));
if (!communicationConfig || !communicationConfig.length) {
this.addCommunicationConfig();
}
if (this.disabled) {
this.deviceProfileCommunicationConfig.disable({emitEvent: false});
if (communicationConfig?.length === this.communicationConfigFormArray.length) {
this.communicationConfigFormArray.patchValue(communicationConfig, {emitEvent: false});
} else {
this.deviceProfileCommunicationConfig.enable({emitEvent: false});
const communicationConfigControl: Array<AbstractControl> = [];
if (communicationConfig) {
communicationConfig.forEach((config) => {
communicationConfigControl.push(this.createdFormGroup(config));
});
}
this.deviceProfileCommunicationConfig.setControl(
'communicationConfig', this.fb.array(communicationConfigControl), {emitEvent: false}
);
if (!communicationConfig || !communicationConfig.length) {
this.addCommunicationConfig();
}
if (this.disabled) {
this.deviceProfileCommunicationConfig.disable({emitEvent: false});
} else {
this.deviceProfileCommunicationConfig.enable({emitEvent: false});
}
}
this.valueChange$ = this.deviceProfileCommunicationConfig.valueChanges.subscribe(() => {
this.updateModel();
});
this.updateUsedSpecType();
if (!this.disabled && !this.deviceProfileCommunicationConfig.valid) {
this.updateModel();
@ -133,16 +132,16 @@ export class SnmpDeviceProfileCommunicationConfigComponent implements OnInit, On
}
public removeCommunicationConfig(index: number) {
this.communicationConfigFormArray().removeAt(index);
this.communicationConfigFormArray.removeAt(index);
}
get isAddEnabled(): boolean {
return this.communicationConfigFormArray().length !== Object.keys(SnmpSpecType).length;
return this.communicationConfigFormArray.length !== Object.keys(SnmpSpecType).length;
}
public addCommunicationConfig() {
this.communicationConfigFormArray().push(this.createdFormGroup());
this.communicationConfigFormArray.push(this.createdFormGroup());
this.deviceProfileCommunicationConfig.updateValueAndValidity();
if (!this.deviceProfileCommunicationConfig.valid) {
this.updateModel();

4
ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-mapping.component.html

@ -25,7 +25,7 @@
</div>
</div>
<mat-divider></mat-divider>
<div *ngFor="let mappingConfig of mappingsConfigFormArray().controls; let $index = index;
<div *ngFor="let mappingConfig of mappingsConfigFormArray.controls; let $index = index;
last as isLast;" fxLayout="row" fxLayoutAlign="start center"
fxLayoutGap="8px" [formGroup]="mappingConfig" class="mapping-list">
<div fxFlex fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start">
@ -64,7 +64,7 @@
</button>
</div>
</div>
<div *ngIf="!mappingsConfigFormArray().controls.length && !disabled">
<div *ngIf="!mappingsConfigFormArray.controls.length && !disabled">
<span fxLayoutAlign="center center" class="tb-prompt required required-text" translate>device-profile.snmp.please-add-mapping-config</span>
</div>
<div *ngIf="!disabled">

59
ui-ngx/src/app/modules/home/components/profile/device/snmp/snmp-device-profile-mapping.component.ts

@ -18,19 +18,20 @@ import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
UntypedFormArray,
UntypedFormBuilder,
UntypedFormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
ValidationErrors,
Validator,
Validators
} from '@angular/forms';
import { SnmpMapping } from '@shared/models/device.models';
import { Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { DataType, DataTypeTranslationMap } from '@shared/models/constants';
import { isUndefinedOrNull } from '@core/utils';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'tb-snmp-device-profile-mapping',
@ -60,7 +61,7 @@ export class SnmpDeviceProfileMappingComponent implements OnInit, OnDestroy, Con
private readonly oidPattern: RegExp = /^\.?([0-2])((\.0)|(\.[1-9][0-9]*))*$/;
private valueChange$: Subscription = null;
private destroy$ = new Subject<void>();
private propagateChange = (v: any) => { };
constructor(private fb: UntypedFormBuilder) { }
@ -69,12 +70,14 @@ export class SnmpDeviceProfileMappingComponent implements OnInit, OnDestroy, Con
this.mappingsConfigForm = this.fb.group({
mappings: this.fb.array([])
});
this.mappingsConfigForm.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => this.updateModel());
}
ngOnDestroy() {
if (this.valueChange$) {
this.valueChange$.unsubscribe();
}
this.destroy$.next();
this.destroy$.complete();
}
registerOnChange(fn: any) {
@ -100,38 +103,36 @@ export class SnmpDeviceProfileMappingComponent implements OnInit, OnDestroy, Con
}
writeValue(mappings: SnmpMapping[]) {
if (this.valueChange$) {
this.valueChange$.unsubscribe();
}
const mappingsControl: Array<AbstractControl> = [];
if (mappings) {
mappings.forEach((config) => {
mappingsControl.push(this.createdFormGroup(config));
});
}
this.mappingsConfigForm.setControl('mappings', this.fb.array(mappingsControl));
if (!mappings || !mappings.length) {
this.addMappingConfig();
}
if (this.disabled) {
this.mappingsConfigForm.disable({emitEvent: false});
if (mappings?.length === this.mappingsConfigFormArray.length) {
this.mappingsConfigFormArray.patchValue(mappings, {emitEvent: false});
} else {
this.mappingsConfigForm.enable({emitEvent: false});
const mappingsControl: Array<AbstractControl> = [];
if (mappings) {
mappings.forEach((config) => {
mappingsControl.push(this.createdFormGroup(config));
});
}
this.mappingsConfigForm.setControl('mappings', this.fb.array(mappingsControl), {emitEvent: false});
if (!mappings || !mappings.length) {
this.addMappingConfig();
}
if (this.disabled) {
this.mappingsConfigForm.disable({emitEvent: false});
} else {
this.mappingsConfigForm.enable({emitEvent: false});
}
}
this.valueChange$ = this.mappingsConfigForm.valueChanges.subscribe(() => {
this.updateModel();
});
if (!this.disabled && !this.mappingsConfigForm.valid) {
this.updateModel();
}
}
mappingsConfigFormArray(): UntypedFormArray {
get mappingsConfigFormArray(): UntypedFormArray {
return this.mappingsConfigForm.get('mappings') as UntypedFormArray;
}
public addMappingConfig() {
this.mappingsConfigFormArray().push(this.createdFormGroup());
this.mappingsConfigFormArray.push(this.createdFormGroup());
this.mappingsConfigForm.updateValueAndValidity();
if (!this.mappingsConfigForm.valid) {
this.updateModel();
@ -139,7 +140,7 @@ export class SnmpDeviceProfileMappingComponent implements OnInit, OnDestroy, Con
}
public removeMappingConfig(index: number) {
this.mappingsConfigFormArray().removeAt(index);
this.mappingsConfigFormArray.removeAt(index);
}
private createdFormGroup(value?: SnmpMapping): UntypedFormGroup {

63
ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts

@ -30,10 +30,11 @@ import {
import { Store } from '@ngrx/store';
import { AppState } from '@app/core/core.state';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { QueueInfo } from '@shared/models/queue.models';
import { UtilsService } from '@core/services/utils.service';
import { guid } from '@core/utils';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'tb-tenant-profile-queues',
@ -70,8 +71,7 @@ export class TenantProfileQueuesComponent implements ControlValueAccessor, Valid
@Input()
disabled: boolean;
private valueChangeSubscription$: Subscription = null;
private destroy$ = new Subject<void>();
private propagateChange = (v: any) => { };
constructor(private store: Store<AppState>,
@ -83,12 +83,6 @@ export class TenantProfileQueuesComponent implements ControlValueAccessor, Valid
this.propagateChange = fn;
}
ngOnDestroy() {
if (this.valueChangeSubscription$) {
this.valueChangeSubscription$.unsubscribe();
}
}
registerOnTouched(fn: any): void {
}
@ -96,6 +90,15 @@ export class TenantProfileQueuesComponent implements ControlValueAccessor, Valid
this.tenantProfileQueuesFormGroup = this.fb.group({
queues: this.fb.array([])
});
this.tenantProfileQueuesFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => this.updateModel());
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
get queuesFormArray(): UntypedFormArray {
@ -112,30 +115,28 @@ export class TenantProfileQueuesComponent implements ControlValueAccessor, Valid
}
writeValue(queues: Array<QueueInfo> | null): void {
if (this.valueChangeSubscription$) {
this.valueChangeSubscription$.unsubscribe();
}
const queuesControls: Array<AbstractControl> = [];
if (queues) {
queues.forEach((queue, index) => {
if (!queue.id) {
if (!this.idMap[index]) {
this.idMap.push(guid());
}
queue.id = this.idMap[index];
}
queuesControls.push(this.fb.control(queue, [Validators.required]));
});
}
this.tenantProfileQueuesFormGroup.setControl('queues', this.fb.array(queuesControls));
if (this.disabled) {
this.tenantProfileQueuesFormGroup.disable({emitEvent: false});
if (queues.length === this.queuesFormArray.length) {
this.queuesFormArray.patchValue(queues, {emitEvent: false});
} else {
this.tenantProfileQueuesFormGroup.enable({emitEvent: false});
const queuesControls: Array<AbstractControl> = [];
if (queues) {
queues.forEach((queue, index) => {
if (!queue.id) {
if (!this.idMap[index]) {
this.idMap.push(guid());
}
queue.id = this.idMap[index];
}
queuesControls.push(this.fb.control(queue, [Validators.required]));
});
}
this.tenantProfileQueuesFormGroup.setControl('queues', this.fb.array(queuesControls), {emitEvent: false});
if (this.disabled) {
this.tenantProfileQueuesFormGroup.disable({emitEvent: false});
} else {
this.tenantProfileQueuesFormGroup.enable({emitEvent: false});
}
}
this.valueChangeSubscription$ = this.tenantProfileQueuesFormGroup.valueChanges.subscribe(() =>
this.updateModel()
);
}
public trackByQueue(index: number, queueControl: AbstractControl) {

8
ui-ngx/src/app/modules/home/components/relation/relation-filters.component.html

@ -17,17 +17,17 @@
-->
<div class="tb-relation-filters" [formGroup]="relationFiltersFormGroup">
<div class="container">
<div class="header" [fxShow]="relationFiltersFormArray().length">
<div class="header" [fxShow]="relationFiltersFormArray.length">
<div fxLayout="row" fxLayoutAlign="start center">
<span class="cell" style="width: 200px; min-width: 200px;" translate>relation.type</span>
<span class="cell" fxFlex translate>entity.entity-types</span>
<span class="cell" style="width: 40px; min-width: 40px;">&nbsp;</span>
</div>
</div>
<div class="body" [fxShow]="relationFiltersFormArray().length">
<div class="body" [fxShow]="relationFiltersFormArray.length">
<div class="row" fxFlex fxLayout="row"
fxLayoutAlign="start center" formArrayName="relationFilters"
*ngFor="let relationFilterControl of relationFiltersFormArray().controls; let $index = index">
*ngFor="let relationFilterControl of relationFiltersFormArray.controls; let $index = index">
<div class="mat-elevation-z1" fxFlex fxLayout="row" fxLayoutAlign="start center" style="padding: 8px 0;">
<tb-relation-type-autocomplete
class="cell" style="width: 200px; min-width: 200px;"
@ -51,7 +51,7 @@
</div>
</div>
</div>
<div class="any-filter" [fxShow]="!relationFiltersFormArray().length">
<div class="any-filter" [fxShow]="!relationFiltersFormArray.length">
<span fxLayoutAlign="center center"
class="tb-prompt" translate>relation.any-relation</span>
</div>

54
ui-ngx/src/app/modules/home/components/relation/relation-filters.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
@ -28,7 +28,8 @@ import { RelationEntityTypeFilter } from '@shared/models/relation.models';
import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'tb-relation-filters',
@ -42,7 +43,7 @@ import { Subscription } from 'rxjs';
}
]
})
export class RelationFiltersComponent extends PageComponent implements ControlValueAccessor, OnInit {
export class RelationFiltersComponent extends PageComponent implements ControlValueAccessor, OnInit, OnDestroy {
@Input() disabled: boolean;
@ -50,22 +51,32 @@ export class RelationFiltersComponent extends PageComponent implements ControlVa
relationFiltersFormGroup: UntypedFormGroup;
private destroy$ = new Subject<void>();
private propagateChange = null;
private valueChangeSubscription: Subscription = null;
constructor(protected store: Store<AppState>,
private fb: UntypedFormBuilder) {
super(store);
}
ngOnInit(): void {
this.relationFiltersFormGroup = this.fb.group({});
this.relationFiltersFormGroup.addControl('relationFilters',
this.fb.array([]));
this.relationFiltersFormGroup = this.fb.group({
relationFilters: this.fb.array([])
});
this.relationFiltersFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => {
this.updateModel();
});
}
relationFiltersFormArray(): UntypedFormArray {
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
get relationFiltersFormArray(): UntypedFormArray {
return this.relationFiltersFormGroup.get('relationFilters') as UntypedFormArray;
}
@ -81,19 +92,17 @@ export class RelationFiltersComponent extends PageComponent implements ControlVa
}
writeValue(filters: Array<RelationEntityTypeFilter>): void {
if (this.valueChangeSubscription) {
this.valueChangeSubscription.unsubscribe();
}
const relationFiltersControls: Array<AbstractControl> = [];
if (filters && filters.length) {
filters.forEach((filter) => {
relationFiltersControls.push(this.createRelationFilterFormGroup(filter));
});
if (filters?.length === this.relationFiltersFormArray.length) {
this.relationFiltersFormArray.patchValue(filters, {emitEvent: false});
} else {
const relationFiltersControls: Array<AbstractControl> = [];
if (filters && filters.length) {
filters.forEach((filter) => {
relationFiltersControls.push(this.createRelationFilterFormGroup(filter));
});
}
this.relationFiltersFormGroup.setControl('relationFilters', this.fb.array(relationFiltersControls), {emitEvent: false});
}
this.relationFiltersFormGroup.setControl('relationFilters', this.fb.array(relationFiltersControls));
this.valueChangeSubscription = this.relationFiltersFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
}
public removeFilter(index: number) {
@ -101,12 +110,11 @@ export class RelationFiltersComponent extends PageComponent implements ControlVa
}
public addFilter() {
const relationFiltersFormArray = this.relationFiltersFormGroup.get('relationFilters') as UntypedFormArray;
const filter: RelationEntityTypeFilter = {
relationType: null,
entityTypes: []
};
relationFiltersFormArray.push(this.createRelationFilterFormGroup(filter));
this.relationFiltersFormArray.push(this.createRelationFilterFormGroup(filter));
}
private createRelationFilterFormGroup(filter: RelationEntityTypeFilter): AbstractControl {

33
ui-ngx/src/app/shared/components/kv-map.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
@ -30,8 +30,9 @@ import {
import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { Subscription } from 'rxjs';
import { SubscriptSizing } from '@angular/material/form-field';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'tb-key-val-map',
@ -50,7 +51,7 @@ import { SubscriptSizing } from '@angular/material/form-field';
}
]
})
export class KeyValMapComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator {
export class KeyValMapComponent extends PageComponent implements ControlValueAccessor, OnInit, OnDestroy, Validator {
@Input() disabled: boolean;
@ -67,19 +68,27 @@ export class KeyValMapComponent extends PageComponent implements ControlValueAcc
kvListFormGroup: UntypedFormGroup;
private destroy$ = new Subject<void>();
private propagateChange = null;
private valueChangeSubscription: Subscription = null;
constructor(protected store: Store<AppState>,
private fb: UntypedFormBuilder) {
super(store);
}
ngOnInit(): void {
this.kvListFormGroup = this.fb.group({});
this.kvListFormGroup.addControl('keyVals',
this.fb.array([]));
this.kvListFormGroup = this.fb.group({
keyVals: this.fb.array([])
});
this.kvListFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => this.updateModel());
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
keyValsFormArray(): UntypedFormArray {
@ -103,9 +112,6 @@ export class KeyValMapComponent extends PageComponent implements ControlValueAcc
}
writeValue(keyValMap: {[key: string]: string}): void {
if (this.valueChangeSubscription) {
this.valueChangeSubscription.unsubscribe();
}
const keyValsControls: Array<AbstractControl> = [];
if (keyValMap) {
for (const property of Object.keys(keyValMap)) {
@ -117,10 +123,7 @@ export class KeyValMapComponent extends PageComponent implements ControlValueAcc
}
}
}
this.kvListFormGroup.setControl('keyVals', this.fb.array(keyValsControls));
this.valueChangeSubscription = this.kvListFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
this.kvListFormGroup.setControl('keyVals', this.fb.array(keyValsControls), {emitEvent: false});
if (this.disabled) {
this.kvListFormGroup.disable({emitEvent: false});
} else {

Loading…
Cancel
Save