Browse Source

Merge fe843614b9 into 9abbcdb40a

pull/15694/merge
Maksym Tsymbarov 4 days ago
committed by GitHub
parent
commit
98429d55fa
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 35
      ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.html
  2. 32
      ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.ts
  3. 12
      ui-ngx/src/app/modules/home/components/calculated-fields/components/calculated-field-arguments/calculated-field-argument-panel.component.ts
  4. 2
      ui-ngx/src/app/modules/home/components/calculated-fields/components/calculated-field-arguments/calculated-field-arguments-table.component.ts
  5. 2
      ui-ngx/src/app/shared/components/entity/entity-list-select.component.html
  6. 10
      ui-ngx/src/app/shared/components/entity/entity-list-select.component.ts
  7. 10
      ui-ngx/src/app/shared/models/calculated-field.models.ts

35
ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.html

@ -56,23 +56,36 @@
/>
</div>
@if (!data.entityId) {
<tb-entity-select formControlName="entityId"
#entitySelect
appearance="outline"
required
entityTypeLabel="{{ 'entity.entity-type' | translate }}"
[filterAllowedEntityTypes]="false"
[allowedEntityTypes]="alarmRuleEntityTypeList"
[defaultEntityType]="EntityType.DEVICE_PROFILE"
(entityChanged)="changeEntity($event)">
</tb-entity-select>
@if (createNew) {
<tb-entity-list-select formControlName="entityId"
#entitySelect
appearance="outline"
required
[filterAllowedEntityTypes]="false"
[allowedEntityTypes]="alarmRuleEntityTypeList"
[predefinedEntityType]="EntityType.DEVICE_PROFILE"
entityTypeLabel="{{ 'entity.entity-type' | translate }}"
displayEntityLabel>
</tb-entity-list-select>
} @else {
<tb-entity-select formControlName="entityId"
#entitySelect
appearance="outline"
required
entityTypeLabel="{{ 'entity.entity-type' | translate }}"
[filterAllowedEntityTypes]="false"
[allowedEntityTypes]="alarmRuleEntityTypeList"
[defaultEntityType]="EntityType.DEVICE_PROFILE"
(entityChanged)="changeEntity($event)">
</tb-entity-select>
}
}
</div>
<ng-container formGroupName="configuration">
<div class="tb-form-panel" [class.disabled]="disabledArguments">
<div class="tb-form-panel-title tb-required">{{ 'calculated-fields.arguments' | translate }}</div>
<tb-calculated-field-arguments-table formControlName="arguments"
[entityId]="data.entityId || fieldFormGroup.get('entityId').value"
[entityId]="data.entityId || selectedEntityId"
[tenantId]="data.tenantId"
[ownerId]="ownerId"
[watchKeyChange]="true"

32
ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.ts

@ -41,7 +41,7 @@ import {
AlarmRuleTestScriptFn
} from "@shared/models/alarm-rule.models";
import { deepTrim } from "@core/utils";
import { combineLatest, Observable } from "rxjs";
import { combineLatest, forkJoin, Observable } from "rxjs";
import { debounceTime, startWith } from "rxjs/operators";
import { RelationTypes } from "@shared/models/relation.models";
import { StringItemsOption } from "@shared/components/string-items-list.component";
@ -51,6 +51,7 @@ import { EntitySelectComponent } from '@shared/components/entity/entity-select.c
import { NULL_UUID } from '@shared/models/id/has-uuid';
import { AssetInfo } from '@shared/models/asset.models';
import { DeviceInfo } from '@shared/models/device.models';
import { EntityTypeListComponent } from '@shared/components/entity/entity-type-list.component';
export interface AlarmRuleDialogData {
value?: CalculatedFieldAlarmRule;
@ -73,7 +74,7 @@ export interface AlarmRuleDialogData {
})
export class AlarmRuleDialogComponent extends DialogComponent<AlarmRuleDialogComponent, CalculatedFieldAlarmRule> {
@ViewChild('entitySelect') entitySelect!: EntitySelectComponent;
@ViewChild('entitySelect') entitySelect!: EntitySelectComponent | EntityTypeListComponent;
fieldFormGroup: FormGroup ;
@ -96,6 +97,7 @@ export class AlarmRuleDialogComponent extends DialogComponent<AlarmRuleDialogCom
disabledClearRuleButton = false;
disabledArguments = false;
isLoading = false;
createNew = false;
constructor(protected store: Store<AppState>,
protected router: Router,
@ -120,6 +122,7 @@ export class AlarmRuleDialogComponent extends DialogComponent<AlarmRuleDialogCom
});
if (!this.data.entityId) {
this.createNew = true;
combineLatest([
this.fieldFormGroup.get('entityId')!.valueChanges.pipe(startWith(this.fieldFormGroup.get('entityId')!.value)),
this.fieldFormGroup.get('name')!.valueChanges.pipe(startWith(this.fieldFormGroup.get('name')!.value))
@ -127,7 +130,7 @@ export class AlarmRuleDialogComponent extends DialogComponent<AlarmRuleDialogCom
debounceTime(50),
takeUntilDestroyed()
).subscribe(([entityId, name]) => {
this.disabledArguments = !entityId || !name?.length;
this.disabledArguments = Array.isArray(entityId) ? !entityId.length : !entityId || !name?.length;
const argsControl = this.fieldFormGroup.get('configuration.arguments')!;
if (this.disabledArguments) {
argsControl.disable({ emitEvent: false });
@ -174,21 +177,34 @@ export class AlarmRuleDialogComponent extends DialogComponent<AlarmRuleDialogCom
add(): void {
if (this.fieldFormGroup.valid && Object.keys(this.arguments ?? {}).length > 0) {
this.isLoading = true;
const alarmRule = { entityId: this.data.entityId, ...(this.data.value ?? {}), ...this.fromGroupValue};
alarmRule.configuration.type = CalculatedFieldType.ALARM;
const entityIds = Array.isArray(this.fieldFormGroup.value.entityId)
? this.fieldFormGroup.value.entityId
: [this.fieldFormGroup.value.entityId ?? this.data.entityId];
this.alarmRulesService.saveAlarmRule(alarmRule)
const requests$ = entityIds.map((entityId: EntityId) => {
const alarmRule = { ...(this.data.value ?? {}), ...this.fromGroupValue, entityId };
alarmRule.configuration.type = CalculatedFieldType.ALARM;
return this.alarmRulesService.saveAlarmRule(alarmRule);
});
forkJoin(requests$)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({
next: calculatedField => this.dialogRef.close(calculatedField),
next: (calculatedFields: CalculatedFieldAlarmRule) => this.dialogRef.close(calculatedFields),
error: () => this.isLoading = false
});
} else {
this.fieldFormGroup.get('name').markAsTouched();
this.entitySelect?.entityAutocompleteMarkAsTouched();
if (this.entitySelect instanceof EntitySelectComponent) {
this.entitySelect?.entityAutocompleteMarkAsTouched();
}
}
}
get selectedEntityId(): EntityId {
return Array.isArray(this.fieldFormGroup.get('entityId').value) ? this.fieldFormGroup.get('entityId').value : this.fieldFormGroup.get('entityId').value;
}
private applyDialogData(): void {
const { configuration = {}, type = CalculatedFieldType.ALARM, debugSettings = { failuresEnabled: true, allEnabled: true }, entityId = this.data.entityId, ...value } = this.data.value ?? {};
this.fieldFormGroup.patchValue({ configuration, type, debugSettings, entityId, ...value }, {emitEvent: false});

12
ui-ngx/src/app/modules/home/components/calculated-fields/components/calculated-field-arguments/calculated-field-argument-panel.component.ts

@ -66,7 +66,7 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit, AfterViewI
@Input() buttonTitle: string;
@Input() argument: CalculatedFieldArgumentValue;
@Input() entityId: EntityId;
@Input() entityId: EntityId | EntityId[];
@Input() tenantId: string;
@Input() entityName: string;
@Input() ownerId: EntityId;
@ -154,7 +154,7 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit, AfterViewI
get enableAttributeScopeSelection(): boolean {
return this.entityType === ArgumentEntityType.Device
|| (this.entityType === ArgumentEntityType.Current
&& (this.entityId.entityType === EntityType.DEVICE || this.entityId.entityType === EntityType.DEVICE_PROFILE))
&& (this.entityIdType === EntityType.DEVICE || this.entityIdType === EntityType.DEVICE_PROFILE))
}
ngOnInit(): void {
@ -221,7 +221,7 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit, AfterViewI
private updatedArgumentType(): void {
let argumentType = ArgumentEntityType.Current;
if (this.argument.refDynamicSourceConfiguration?.type === ArgumentEntityType.Owner) {
this.enableAutocomplete = (this.entityId.entityType === EntityType.DEVICE_PROFILE || this.entityId.entityType === EntityType.ASSET_PROFILE);
this.enableAutocomplete = (this.entityIdType === EntityType.DEVICE_PROFILE || this.entityIdType === EntityType.ASSET_PROFILE);
argumentType = ArgumentEntityType.Owner;
} else if (this.argument.refEntityId?.entityType) {
argumentType = this.argument.refEntityId.entityType;
@ -294,7 +294,7 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit, AfterViewI
.pipe(distinctUntilChanged(), takeUntilDestroyed())
.subscribe(type => {
this.argumentFormGroup.get('refEntityId').setValue(null);
this.enableAutocomplete = (this.entityId.entityType === EntityType.DEVICE_PROFILE || this.entityId.entityType === EntityType.ASSET_PROFILE) && type === ArgumentEntityType.Owner;
this.enableAutocomplete = (this.entityIdType === EntityType.DEVICE_PROFILE || this.entityIdType === EntityType.ASSET_PROFILE) && type === ArgumentEntityType.Owner;
this.updatedRefEntityIdState(type);
if (!this.enableAttributeScopeSelection) {
this.refEntityKeyFormGroup.get('scope').setValue(AttributeScope.SERVER_SCOPE);
@ -341,4 +341,8 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit, AfterViewI
this.entityNameSubject.next(null);
}
}
get entityIdType() {
return Array.isArray(this.entityId) ? this.entityId[0].entityType : this.entityId.entityType;
}
}

2
ui-ngx/src/app/modules/home/components/calculated-fields/components/calculated-field-arguments/calculated-field-arguments-table.component.ts

@ -84,7 +84,7 @@ import { BaseData } from '@shared/models/base-data';
})
export class CalculatedFieldArgumentsTableComponent implements ControlValueAccessor, Validator, OnChanges, AfterViewInit {
@Input() entityId: EntityId;
@Input() entityId: EntityId | EntityId[];
@Input() tenantId: string;
@Input() entityName: string;
@Input() ownerId: EntityId;

2
ui-ngx/src/app/shared/components/entity/entity-list-select.component.html

@ -21,6 +21,7 @@
[inlineField]="inlineField"
[class.flex-1]="inlineField && !modelValue.entityType"
style="min-width: 100px; padding-right: 8px;"
[label]="entityTypeLabel ?? null"
[showLabel]="true"
[required]="required"
subscriptSizing="dynamic"
@ -35,6 +36,7 @@
@if (modelValue.entityType) {
<tb-entity-list
class="flex-1"
[labelText]="displayEntityLabel ? (entityTypeTranslations.get(modelValue.entityType).typePlural | translate) : ''"
[inlineField]="inlineField"
[class.tb-not-empty]="modelValue.ids?.length > 0"
[required]="required"

10
ui-ngx/src/app/shared/components/entity/entity-list-select.component.ts

@ -16,7 +16,7 @@
import { booleanAttribute, Component, DestroyRef, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { AliasEntityType, EntityType } from '@shared/models/entity-type.models';
import { AliasEntityType, EntityType, entityTypeTranslations } from '@shared/models/entity-type.models';
import { EntityService } from '@core/http/entity.service';
import { EntityId } from '@shared/models/id/entity-id';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@ -76,8 +76,16 @@ export class EntityListSelectComponent implements ControlValueAccessor, OnInit {
@Input()
appearance: MatFormFieldAppearance = 'fill';
@Input()
entityTypeLabel: string;
@Input({transform: booleanAttribute})
displayEntityLabel: boolean;
displayEntityTypeSelect: boolean;
readonly entityTypeTranslations = entityTypeTranslations;
private defaultEntityType: EntityType | AliasEntityType = null;
private propagateChange = (_v: any) => { };

10
ui-ngx/src/app/shared/models/calculated-field.models.ts

@ -33,6 +33,7 @@ import { EntitySearchDirection } from '@shared/models/relation.models';
import { AbstractControl, FormControl, ValidationErrors, ValidatorFn } from '@angular/forms';
import { AlarmRule } from "@shared/models/alarm-rule.models";
import { AlarmSeverity } from "@shared/models/alarm.models";
import { EntityFilter } from '@shared/models/query/query.models';
export const FORBIDDEN_NAMES = ['ctx', 'e', 'pi'];
@ -527,7 +528,14 @@ export const ArgumentEntityTypeParamsMap =new Map<ArgumentEntityType, ArgumentEn
[ArgumentEntityType.Customer, { title: 'calculated-fields.customer-name', entityType: EntityType.CUSTOMER }],
])
export const getCalculatedFieldCurrentEntityFilter = (entityName: string, entityId: EntityId) => {
export const getCalculatedFieldCurrentEntityFilter = (entityName: string, entityId: EntityId | EntityId[]): EntityFilter => {
if (Array.isArray(entityId)) {
return {
type: AliasFilterType.entityList,
entityType: entityId[0].entityType as EntityType,
entityList: entityId.map(value => value.id)
}
}
switch (entityId?.entityType) {
case EntityType.ASSET_PROFILE:
return {

Loading…
Cancel
Save