Browse Source

Changed getAll endpoint and refactoring

pull/12509/head
mpetrov 1 year ago
parent
commit
a82d3690f3
  1. 5
      ui-ngx/src/app/core/http/calculated-fields.service.ts
  2. 16
      ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts
  3. 138
      ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.html
  4. 1
      ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.scss
  5. 101
      ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts
  6. 4
      ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html
  7. 4
      ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts
  8. 53
      ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.html
  9. 9
      ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts
  10. 1
      ui-ngx/src/app/modules/home/components/calculated-fields/components/public-api.ts
  11. 3
      ui-ngx/src/app/modules/home/pages/device/device-tabs.component.html
  12. 4
      ui-ngx/src/app/modules/home/pages/device/device-tabs.component.ts
  13. 9
      ui-ngx/src/app/shared/components/entity/entity-key-autocomplete.component.ts
  14. 1
      ui-ngx/src/app/shared/models/calculated-field.models.ts

5
ui-ngx/src/app/core/http/calculated-fields.service.ts

@ -21,6 +21,7 @@ import { HttpClient } from '@angular/common/http';
import { PageData } from '@shared/models/page/page-data';
import { CalculatedField } from '@shared/models/calculated-field.models';
import { PageLink } from '@shared/models/page/page-link';
import { EntityId } from '@shared/models/id/entity-id';
@Injectable({
providedIn: 'root'
@ -43,8 +44,8 @@ export class CalculatedFieldsService {
return this.http.delete<boolean>(`/api/calculatedField/${calculatedFieldId}`, defaultHttpOptionsFromConfig(config));
}
public getCalculatedFields(pageLink: PageLink, config?: RequestConfig): Observable<PageData<CalculatedField>> {
return this.http.get<PageData<any>>(`/api/calculatedFields${pageLink.toQuery()}`,
public getCalculatedFields({ entityType, id }: EntityId, pageLink: PageLink, config?: RequestConfig): Observable<PageData<CalculatedField>> {
return this.http.get<PageData<CalculatedField>>(`/api/${entityType}/${id}/calculatedFields${pageLink.toQuery()}`,
defaultHttpOptionsFromConfig(config));
}
}

16
ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts

@ -40,6 +40,7 @@ import { CalculatedFieldDialogComponent } from './components/public-api';
export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedField, TimePageLink> {
// TODO: [Calculated Fields] remove hardcode when BE variable implemented
readonly calculatedFieldsDebugPerTenantLimitsConfiguration =
getCurrentAuthState(this.store)['calculatedFieldsDebugPerTenantLimitsConfiguration'] || '1:1';
readonly maxDebugModeDuration = getCurrentAuthState(this.store).maxDebugModeDurationMinutes * MINUTE;
@ -66,9 +67,9 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
this.entityType = EntityType.CALCULATED_FIELD;
this.entityTranslations = entityTypeTranslations.get(EntityType.CALCULATED_FIELD);
this.entitiesFetchFunction = pageLink => this.fetchCalculatedFields(pageLink);
this.entitiesFetchFunction = (pageLink: TimePageLink) => this.fetchCalculatedFields(pageLink);
this.addEntity = this.addCalculatedField.bind(this);
this.deleteEntityTitle = (field) => this.translate.instant('calculated-fields.delete-title', {title: field.name});
this.deleteEntityTitle = (field: CalculatedField) => this.translate.instant('calculated-fields.delete-title', {title: field.name});
this.deleteEntityContent = () => this.translate.instant('calculated-fields.delete-text');
this.deleteEntitiesTitle = count => this.translate.instant('calculated-fields.delete-multiple-title', {count});
this.deleteEntitiesContent = () => this.translate.instant('calculated-fields.delete-multiple-text');
@ -102,7 +103,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
}
fetchCalculatedFields(pageLink: TimePageLink): Observable<PageData<CalculatedField>> {
return this.calculatedFieldsService.getCalculatedFields(pageLink);
return this.calculatedFieldsService.getCalculatedFields(this.entityId, pageLink);
}
onOpenDebugConfig($event: Event, { debugSettings = {}, id }: CalculatedField): void {
@ -134,10 +135,9 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
private addCalculatedField(): void {
this.getCalculatedFieldDialog()
.afterClosed()
.pipe(
filter(Boolean),
switchMap(calculatedField => this.calculatedFieldsService.saveCalculatedField({ entityId: this.entityId, ...calculatedField} as any)),
switchMap(calculatedField => this.calculatedFieldsService.saveCalculatedField({ entityId: this.entityId, ...calculatedField })),
)
.subscribe((res) => {
if (res) {
@ -148,10 +148,9 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
private editCalculatedField(calculatedField: CalculatedField): void {
this.getCalculatedFieldDialog(calculatedField, 'action.apply')
.afterClosed()
.pipe(
filter(Boolean),
switchMap((updatedCalculatedField) => this.calculatedFieldsService.saveCalculatedField({ ...calculatedField, ...updatedCalculatedField} as any)),
switchMap((updatedCalculatedField) => this.calculatedFieldsService.saveCalculatedField({ ...calculatedField, ...updatedCalculatedField })),
)
.subscribe((res) => {
if (res) {
@ -160,7 +159,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
});
}
private getCalculatedFieldDialog(value = {}, buttonTitle = 'action.add') {
private getCalculatedFieldDialog(value = {}, buttonTitle = 'action.add'): Observable<CalculatedField> {
return this.dialog.open<CalculatedFieldDialogComponent, any, CalculatedField>(CalculatedFieldDialogComponent, {
disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
@ -172,6 +171,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
tenantId: this.tenantId,
}
})
.afterClosed()
}
private getDebugConfigLabel(debugSettings: EntityDebugSettings): string {

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

@ -22,79 +22,83 @@
<div class="tb-form-table-header-cell w-[17%]">{{ 'common.type' | translate }}</div>
<div class="tb-form-table-header-cell w-[31%]">{{ 'entity.key' | translate }}</div>
</div>
<div class="tb-form-table-body tb-drop-list">
@for (group of argumentsFormArray.controls; track group) {
<div [formGroup]="group" class="tb-form-table-row">
<mat-form-field appearance="outline" class="tb-inline-field w-1/6" subscriptSizing="dynamic">
<input matInput formControlName="argumentName" placeholder="{{ 'action.set' | translate }}">
</mat-form-field>
@if (group.get('refEntityId')?.get('id').value) {
<ng-container [formGroup]="group.get('refEntityId')">
<mat-form-field appearance="outline" class="tb-inline-field w-1/6" subscriptSizing="dynamic">
<mat-select [value]="group.get('refEntityId').get('entityType').value" formControlName="entityType">
<mat-option [value]="group.get('refEntityId').get('entityType').value">
{{ entityTypeTranslations.get(group.get('refEntityId').get('entityType').value)?.type | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<tb-entity-autocomplete
class="inline-entity-autocomplete w-1/6"
formControlName="id"
[withLabel]="false"
[placeholder]="'action.set' | translate"
[appearance]="'outline'"
[subscriptSizing]="'dynamic'"
[entityType]="group.get('refEntityId').get('entityType').value"/>
</ng-container>
} @else {
<mat-form-field appearance="outline" class="tb-inline-field w-[calc(33.3%+12px)]" subscriptSizing="dynamic">
<mat-select [value]="'current'" [disabled]="true">
<mat-option [value]="'current'">
{{ (group.get('refEntityId')?.get('entityType').value === ArgumentEntityType.Tenant
? 'calculated-fields.argument-current-tenant'
: 'calculated-fields.argument-current') | translate }}
</mat-option>
</mat-select>
</mat-form-field>
}
<ng-container [formGroup]="group.get('refEntityKey')">
<div class="tb-form-table-body tb-drop-list">
@for (group of argumentsFormArray.controls; track group) {
<div [formGroup]="group" class="tb-form-table-row">
<mat-form-field appearance="outline" class="tb-inline-field w-1/6" subscriptSizing="dynamic">
<input matInput formControlName="argumentName" placeholder="{{ 'action.set' | translate }}">
</mat-form-field>
@if (group.get('refEntityId')?.get('id').value) {
<ng-container [formGroup]="group.get('refEntityId')">
<mat-form-field appearance="outline" class="tb-inline-field w-1/6" subscriptSizing="dynamic">
<mat-select [value]="group.get('refEntityKey').get('type').value" formControlName="type">
<mat-option [value]="group.get('refEntityKey').get('type').value">
{{ ArgumentTypeTranslations.get(group.get('refEntityKey').get('type').value) | translate }}
<mat-select [value]="group.get('refEntityId').get('entityType').value" formControlName="entityType">
<mat-option [value]="group.get('refEntityId').get('entityType').value">
{{ entityTypeTranslations.get(group.get('refEntityId').get('entityType').value)?.type | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-chip-listbox formControlName="key" class="tb-inline-field w-1/6">
<mat-chip>
<div tbTruncateWithTooltip class="max-w-25">
{{group.get('refEntityKey').get('key').value}}
</div>
</mat-chip>
</mat-chip-listbox>
<tb-entity-autocomplete
class="inline-entity-autocomplete w-1/6"
formControlName="id"
[withLabel]="false"
[placeholder]="'action.set' | translate"
[appearance]="'outline'"
[subscriptSizing]="'dynamic'"
[entityType]="group.get('refEntityId').get('entityType').value"/>
</ng-container>
<div class="flex opacity-55">
<button type="button"
mat-icon-button
#button
(click)="manageArgument($event, button, $index)"
[matTooltip]="'action.edit' | translate"
matTooltipPosition="above">
<mat-icon>edit</mat-icon>
</button>
<button type="button"
mat-icon-button
(click)="onDelete($index)"
[matTooltip]="'action.delete' | translate"
matTooltipPosition="above">
<mat-icon>delete</mat-icon>
</button>
</div>
} @else {
<mat-form-field appearance="outline" class="tb-inline-field w-[calc(33.3%+12px)]" subscriptSizing="dynamic">
<mat-select [value]="'current'" [disabled]="true">
<mat-option [value]="'current'">
{{
(group.get('refEntityId')?.get('entityType').value === ArgumentEntityType.Tenant
? 'calculated-fields.argument-current-tenant'
: 'calculated-fields.argument-current') | translate
}}
</mat-option>
</mat-select>
</mat-form-field>
}
<ng-container [formGroup]="group.get('refEntityKey')">
<mat-form-field appearance="outline" class="tb-inline-field w-1/6" subscriptSizing="dynamic">
@if (group.get('refEntityKey').get('type').value; as type) {
<mat-select [value]="type" formControlName="type">
<mat-option [value]="type">
{{ ArgumentTypeTranslations.get(type) | translate }}
</mat-option>
</mat-select>
}
</mat-form-field>
<mat-chip-listbox formControlName="key" class="tb-inline-field w-1/6">
<mat-chip>
<div tbTruncateWithTooltip class="max-w-25">
{{ group.get('refEntityKey').get('key').value }}
</div>
</mat-chip>
</mat-chip-listbox>
</ng-container>
<div class="flex opacity-55">
<button type="button"
mat-icon-button
#button
(click)="manageArgument($event, button, $index)"
[matTooltip]="'action.edit' | translate"
matTooltipPosition="above">
<mat-icon>edit</mat-icon>
</button>
<button type="button"
mat-icon-button
(click)="onDelete($index)"
[matTooltip]="'action.delete' | translate"
matTooltipPosition="above">
<mat-icon>delete</mat-icon>
</button>
</div>
} @empty {
<span class="tb-prompt flex items-center justify-center">{{ 'calculated-fields.no-arguments' | translate }}</span>
}
</div>
</div>
} @empty {
<span class="tb-prompt flex items-center justify-center">{{ 'calculated-fields.no-arguments' | translate }}</span>
}
</div>
@if (errorText) {
<tb-error noMargin [error]="errorText | translate" class="pl-3"/>
}

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

@ -25,6 +25,7 @@
line-height: 20px;
}
}
a {
font-size: 14px;
}

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

@ -43,9 +43,7 @@ import {
CalculatedFieldArgumentValue,
CalculatedFieldType,
} from '@shared/models/calculated-field.models';
import {
CalculatedFieldArgumentPanelComponent
} from '@home/components/calculated-fields/components/panel/calculated-field-argument-panel.component';
import { CalculatedFieldArgumentPanelComponent } from '@home/components/calculated-fields/components/public-api';
import { MatButton } from '@angular/material/button';
import { TbPopoverService } from '@shared/components/popover.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@ -87,7 +85,7 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
readonly EntityType = EntityType;
readonly ArgumentEntityType = ArgumentEntityType;
private onChange: (argumentsObj: Record<string, CalculatedFieldArgument>) => void = () => {};
private propagateChange: (argumentsObj: Record<string, CalculatedFieldArgument>) => void = () => {};
constructor(
private fb: FormBuilder,
@ -98,59 +96,27 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
private renderer: Renderer2
) {
this.argumentsFormArray.valueChanges.pipe(takeUntilDestroyed()).subscribe(() => {
this.onChange(this.getArgumentsObject());
this.propagateChange(this.getArgumentsObject());
});
effect(() => this.calculatedFieldType() && this.argumentsFormArray.updateValueAndValidity());
}
registerOnChange(fn: (argumentsObj: Record<string, CalculatedFieldArgument>) => void): void {
this.onChange = fn;
this.propagateChange = fn;
}
registerOnTouched(_): void {}
validate(): ValidationErrors | null {
if (this.calculatedFieldType() === CalculatedFieldType.SIMPLE
&& this.argumentsFormArray.controls.some(control => control.get('refEntityKey').get('type').value === ArgumentType.Rolling)) {
this.errorText = 'calculated-fields.hint.arguments-simple-with-rolling';
} else if (!this.argumentsFormArray.controls.length) {
this.errorText = 'calculated-fields.hint.arguments-empty';
} else {
this.errorText = '';
}
this.updateErrorText();
return this.errorText ? { argumentsFormArray: false } : null;
}
private getArgumentsObject(): Record<string, CalculatedFieldArgument> {
return this.argumentsFormArray.controls.reduce((acc, control) => {
const rawValue = control.getRawValue();
const { argumentName, ...argument } = rawValue as CalculatedFieldArgumentValue;
acc[argumentName] = argument;
return acc;
}, {} as Record<string, CalculatedFieldArgument>);
}
writeValue(argumentsObj: Record<string, CalculatedFieldArgument>): void {
this.argumentsFormArray.clear();
Object.keys(argumentsObj).forEach(key => {
this.argumentsFormArray.push(this.fb.group({
argumentName: [key, [Validators.required, Validators.maxLength(255), Validators.pattern(noLeadTrailSpacesRegex)]],
...argumentsObj[key],
...(argumentsObj[key].refEntityId ? {
refEntityId: this.fb.group({
entityType: [{ value: argumentsObj[key].refEntityId.entityType, disabled: true }],
id: [{ value: argumentsObj[key].refEntityId.id , disabled: true }],
}),
} : {}),
refEntityKey: this.fb.group({
type: [{ value: argumentsObj[key].refEntityKey.type, disabled: true }],
key: [{ value: argumentsObj[key].refEntityKey.key, disabled: true }],
}),
}) as AbstractControl);
});
onDelete(index: number): void {
this.argumentsFormArray.removeAt(index);
this.argumentsFormArray.markAsDirty();
}
manageArgument($event: Event, matButton: MatButton, index?: number): void {
$event?.stopPropagation();
const trigger = matButton._elementRef.nativeElement;
@ -189,7 +155,51 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
}
}
getArgumentFormGroup(value: CalculatedFieldArgumentValue): AbstractControl {
private updateErrorText(): void {
if (this.calculatedFieldType() === CalculatedFieldType.SIMPLE
&& this.argumentsFormArray.controls.some(control => control.get('refEntityKey').get('type').value === ArgumentType.Rolling)) {
this.errorText = 'calculated-fields.hint.arguments-simple-with-rolling';
} else if (!this.argumentsFormArray.controls.length) {
this.errorText = 'calculated-fields.hint.arguments-empty';
} else {
this.errorText = '';
}
}
private getArgumentsObject(): Record<string, CalculatedFieldArgument> {
return this.argumentsFormArray.controls.reduce((acc, control) => {
const rawValue = control.getRawValue();
const { argumentName, ...argument } = rawValue as CalculatedFieldArgumentValue;
acc[argumentName] = argument;
return acc;
}, {} as Record<string, CalculatedFieldArgument>);
}
writeValue(argumentsObj: Record<string, CalculatedFieldArgument>): void {
this.argumentsFormArray.clear();
this.populateArgumentsFormArray(argumentsObj)
}
private populateArgumentsFormArray(argumentsObj: Record<string, CalculatedFieldArgument>): void {
Object.keys(argumentsObj).forEach(key => {
this.argumentsFormArray.push(this.fb.group({
argumentName: [key, [Validators.required, Validators.maxLength(255), Validators.pattern(noLeadTrailSpacesRegex)]],
...argumentsObj[key],
...(argumentsObj[key].refEntityId ? {
refEntityId: this.fb.group({
entityType: [{ value: argumentsObj[key].refEntityId.entityType, disabled: true }],
id: [{ value: argumentsObj[key].refEntityId.id , disabled: true }],
}),
} : {}),
refEntityKey: this.fb.group({
type: [{ value: argumentsObj[key].refEntityKey.type, disabled: true }],
key: [{ value: argumentsObj[key].refEntityKey.key, disabled: true }],
}),
}) as AbstractControl);
});
}
private getArgumentFormGroup(value: CalculatedFieldArgumentValue): AbstractControl {
return this.fb.group({
...value,
argumentName: [value.argumentName, [Validators.required, Validators.maxLength(255), Validators.pattern(noLeadTrailSpacesRegex)]],
@ -205,9 +215,4 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
}),
})
}
onDelete(index: number): void {
this.argumentsFormArray.removeAt(index);
this.argumentsFormArray.markAsDirty();
}
}

4
ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html

@ -68,7 +68,7 @@
formControlName="arguments"
[entityId]="data.entityId"
[tenantId]="data.tenantId"
[calculatedFieldType]="fieldFormGroup.get('type').valueChanges | async"
[calculatedFieldType]="fieldFormGroup.get('type').value"
/>
</div>
<div class="tb-form-panel">
@ -96,7 +96,7 @@
[functionArgs]="functionArgs$ | async"
[disableUndefinedCheck]="true"
[scriptLanguage]="ScriptLanguage.TBEL"
helpId="[TODO]: ADD VALID LINK HERE!!!"
helpId="[TODO]: [Calculated Fields] add valid link"
/>
}
</div>

4
ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts

@ -47,7 +47,7 @@ export class CalculatedFieldDialogComponent extends DialogComponent<CalculatedFi
fieldFormGroup = this.fb.group({
name: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex), Validators.maxLength(255)]],
type: [CalculatedFieldType.SIMPLE, [Validators.required]],
type: [CalculatedFieldType.SIMPLE],
debugSettings: [],
configuration: this.fb.group({
arguments: [{}],
@ -72,7 +72,7 @@ export class CalculatedFieldDialogComponent extends DialogComponent<CalculatedFi
readonly EntityType = EntityType;
readonly CalculatedFieldType = CalculatedFieldType;
readonly ScriptLanguage = ScriptLanguage;
readonly helpLink = `${helpBaseUrl}/[TODO: ADD VALID LINK!!!]`;
readonly helpLink = `${helpBaseUrl}/[TODO: [Calculated Fields] add valid link]`;
readonly fieldTypes = Object.values(CalculatedFieldType) as CalculatedFieldType[];
readonly outputTypes = Object.values(OutputType) as OutputType[];
readonly CalculatedFieldTypeTranslations = CalculatedFieldTypeTranslations;

53
ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.html

@ -24,30 +24,32 @@
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput name="value" formControlName="argumentName" maxlength="255" placeholder="{{ 'action.set' | translate }}"/>
@if (argumentFormGroup.get('argumentName').hasError('required') && argumentFormGroup.get('argumentName').touched) {
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="'calculated-fields.hint.argument-name-required' | translate"
class="tb-error">
warning
</mat-icon>
} @else if (argumentFormGroup.get('argumentName').hasError('pattern') && argumentFormGroup.get('argumentName').touched) {
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="'calculated-fields.hint.argument-name-pattern' | translate"
class="tb-error">
warning
</mat-icon>
} @else if (argumentFormGroup.get('argumentName').hasError('maxlength') && argumentFormGroup.get('argumentName').touched) {
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="'calculated-fields.hint.argument-name-max-length' | translate"
class="tb-error">
warning
</mat-icon>
@if (argumentFormGroup.get('argumentName').touched) {
@if (argumentFormGroup.get('argumentName').hasError('required')) {
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="'calculated-fields.hint.argument-name-required' | translate"
class="tb-error">
warning
</mat-icon>
} @else if (argumentFormGroup.get('argumentName').hasError('pattern')) {
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="'calculated-fields.hint.argument-name-pattern' | translate"
class="tb-error">
warning
</mat-icon>
} @else if (argumentFormGroup.get('argumentName').hasError('maxlength')) {
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="'calculated-fields.hint.argument-name-max-length' | translate"
class="tb-error">
warning
</mat-icon>
}
}
</mat-form-field>
</div>
@ -118,7 +120,7 @@
@if (refEntityKeyFormGroup.get('type').value !== ArgumentType.Attribute) {
<div class="tb-form-row">
<div class="fixed-title-width tb-required">{{ 'calculated-fields.timeseries-key' | translate }}</div>
<tb-entity-key-autocomplete formControlName="key" [dataKeyType]="DataKeyType.timeseries" [entityFilter]="entityFilter"/>
<tb-entity-key-autocomplete class="w-full" formControlName="key" [dataKeyType]="DataKeyType.timeseries" [entityFilter]="entityFilter"/>
</div>
} @else {
<div class="tb-form-row">
@ -143,6 +145,7 @@
<div class="fixed-title-width tb-required">{{ 'calculated-fields.attribute-key' | translate }}</div>
<tb-entity-key-autocomplete
formControlName="key"
class="w-full"
[dataKeyType]="DataKeyType.attribute"
[entityFilter]="entityFilter"
[keyScopeType]="argumentFormGroup.get('refEntityKey').get('scope').value"

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

@ -88,6 +88,7 @@ export class CalculatedFieldArgumentPanelComponent extends PageComponent impleme
readonly datasourceType = DatasourceType;
readonly ArgumentTypeTranslations = ArgumentTypeTranslations;
readonly AttributeScope = AttributeScope;
readonly ArgumentEntityType = ArgumentEntityType;
constructor(
private fb: FormBuilder,
@ -164,9 +165,9 @@ export class CalculatedFieldArgumentPanelComponent extends PageComponent impleme
private observeEntityFilterChanges(): void {
merge(
this.argumentFormGroup.get('refEntityId').get('entityType').valueChanges,
this.argumentFormGroup.get('refEntityId').get('id').valueChanges.pipe(filter(Boolean)),
this.argumentFormGroup.get('refEntityKey').get('scope').valueChanges,
this.refEntityIdFormGroup.get('entityType').valueChanges,
this.refEntityIdFormGroup.get('id').valueChanges.pipe(filter(Boolean)),
this.refEntityKeyFormGroup.get('scope').valueChanges,
)
.pipe(debounceTime(300), delay(50), takeUntilDestroyed())
.subscribe(() => this.updateEntityFilter(this.entityType));
@ -196,6 +197,4 @@ export class CalculatedFieldArgumentPanelComponent extends PageComponent impleme
typeControl.updateValueAndValidity();
}
}
protected readonly ArgumentEntityType = ArgumentEntityType;
}

1
ui-ngx/src/app/modules/home/components/calculated-fields/components/public-api.ts

@ -16,3 +16,4 @@
export * from './dialog/calculated-field-dialog.component';
export * from './arguments-table/calculated-field-arguments-table.component';
export * from './panel/calculated-field-argument-panel.component';

3
ui-ngx/src/app/modules/home/pages/device/device-tabs.component.html

@ -32,8 +32,7 @@
[entityName]="entity.name">
</tb-attribute-table>
</mat-tab>
<mat-tab *ngIf="entity"
label="{{ 'entity.type-calculated-fields' | translate }}" #calculatedFieldsTab="matTab">
<mat-tab *ngIf="entity" label="{{ 'entity.type-calculated-fields' | translate }}" #calculatedFieldsTab="matTab">
<tb-calculated-fields-table [active]="calculatedFieldsTab.isActive" [entityId]="entity.id"/>
</mat-tab>
<mat-tab *ngIf="entity"

4
ui-ngx/src/app/modules/home/pages/device/device-tabs.component.ts

@ -19,7 +19,6 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { DeviceInfo } from '@shared/models/device.models';
import { EntityTabsComponent } from '../../components/entity/entity-tabs.component';
import { EntityType } from '@shared/models/entity-type.models';
@Component({
selector: 'tb-device-tabs',
@ -28,8 +27,6 @@ import { EntityType } from '@shared/models/entity-type.models';
})
export class DeviceTabsComponent extends EntityTabsComponent<DeviceInfo> {
readonly EntityType = EntityType;
constructor(protected store: Store<AppState>) {
super(store);
}
@ -37,4 +34,5 @@ export class DeviceTabsComponent extends EntityTabsComponent<DeviceInfo> {
ngOnInit() {
super.ngOnInit();
}
}

9
ui-ngx/src/app/shared/components/entity/entity-key-autocomplete.component.ts

@ -47,9 +47,6 @@ import { EntityFilter } from '@shared/models/query/query.models';
multi: true
}
],
host: {
class: 'w-full'
}
})
export class EntityKeyAutocompleteComponent implements ControlValueAccessor, Validator {
@ -63,7 +60,7 @@ export class EntityKeyAutocompleteComponent implements ControlValueAccessor, Val
searchText = '';
keyInputSubject = new Subject<void>();
private onChange: (value: string) => void;
private propagateChange: (value: string) => void;
private cachedResult: EntitiesKeysByQuery;
keys$ = this.keyInputSubject.asObservable()
@ -101,7 +98,7 @@ export class EntityKeyAutocompleteComponent implements ControlValueAccessor, Val
) {
this.keyControl.valueChanges
.pipe(takeUntilDestroyed())
.subscribe(value => this.onChange(value));
.subscribe(value => this.propagateChange(value));
effect(() => {
if (this.keyScopeType() || this.entityFilter() && this.dataKeyType()) {
this.cachedResult = null;
@ -119,7 +116,7 @@ export class EntityKeyAutocompleteComponent implements ControlValueAccessor, Val
}
registerOnChange(onChange: (value: string) => void): void {
this.onChange = onChange;
this.propagateChange = onChange;
}
registerOnTouched(_): void {}

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

@ -25,6 +25,7 @@ export interface CalculatedField extends Omit<BaseData<CalculatedFieldId>, 'labe
externalId?: string;
configuration: CalculatedFieldConfiguration;
type: CalculatedFieldType;
entityId: EntityId;
}
export enum CalculatedFieldType {

Loading…
Cancel
Save