Browse Source

Merge pull request #12591 from maxunbearable/feature/calculated-fields-adjustments

Calculated fields adjustments, improvements and fixes
pull/12603/head
Vladyslav Prykhodko 1 year ago
committed by GitHub
parent
commit
634ff46ef7
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts
  2. 4
      ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table.component.ts
  3. 13
      ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.html
  4. 8
      ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.scss
  5. 16
      ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts
  6. 3
      ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html
  7. 6
      ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts
  8. 2
      ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.html
  9. 30
      ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts
  10. 4
      ui-ngx/src/app/modules/home/pages/asset-profile/asset-profile-tabs.component.html
  11. 4
      ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.html
  12. 4
      ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.html
  13. 22
      ui-ngx/src/app/shared/models/calculated-field.models.ts

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

@ -54,7 +54,8 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
private durationLeft: DurationLeftPipe,
private popoverService: TbPopoverService,
private destroyRef: DestroyRef,
private renderer: Renderer2
private renderer: Renderer2,
public entityName: string
) {
super();
this.tableTitle = this.translate.instant('entity.type-calculated-fields');
@ -159,6 +160,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
entityId: this.entityId,
debugLimitsConfiguration: this.calculatedFieldsDebugPerTenantLimitsConfiguration,
tenantId: this.tenantId,
entityName: this.entityName,
}
})
.afterClosed();

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

@ -47,6 +47,7 @@ export class CalculatedFieldsTableComponent {
active = input<boolean>();
entityId = input<EntityId>();
entityName = input<string>();
calculatedFieldsTableConfig: CalculatedFieldsTableConfig;
@ -71,7 +72,8 @@ export class CalculatedFieldsTableComponent {
this.durationLeft,
this.popoverService,
this.destroyRef,
this.renderer
this.renderer,
this.entityName()
);
this.cd.markForCheck();
}

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

@ -80,14 +80,23 @@
</mat-chip>
</mat-chip-listbox>
</ng-container>
<div class="flex opacity-55">
<div class="tb-form-table-row-cell-buttons flex">
<button type="button"
mat-icon-button
#button
(click)="manageArgument($event, button, $index)"
[matTooltip]="'action.edit' | translate"
matTooltipPosition="above">
<mat-icon>edit</mat-icon>
<mat-icon
[matBadgeHidden]="!(argumentsFormArray.dirty
&& group.get('refEntityKey').get('type').value === ArgumentType.Rolling
&& calculatedFieldType() === CalculatedFieldType.SIMPLE)"
matBadgeColor="warn"
matBadgeSize="small"
matBadge="*"
>
edit
</mat-icon>
</button>
<button type="button"
mat-icon-button

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

@ -13,6 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
:host {
.tb-form-table-row-cell-buttons {
--mat-badge-legacy-small-size-container-size: 8px;
--mat-badge-small-size-container-overlap-offset: -5px;
--mat-badge-small-size-text-size: 0;
}
}
:host ::ng-deep {
.tb-inline-field {
a {

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

@ -21,7 +21,9 @@ import {
forwardRef,
input,
Input,
OnChanges,
Renderer2,
SimpleChanges,
ViewContainerRef,
} from '@angular/core';
import {
@ -70,10 +72,11 @@ import { TbPopoverComponent } from '@shared/components/popover.component';
}
],
})
export class CalculatedFieldArgumentsTableComponent implements ControlValueAccessor, Validator {
export class CalculatedFieldArgumentsTableComponent implements ControlValueAccessor, Validator, OnChanges {
@Input() entityId: EntityId;
@Input() tenantId: string;
@Input() entityName: string;
calculatedFieldType = input<CalculatedFieldType>()
@ -84,6 +87,8 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
readonly ArgumentTypeTranslations = ArgumentTypeTranslations;
readonly EntityType = EntityType;
readonly ArgumentEntityType = ArgumentEntityType;
readonly ArgumentType = ArgumentType;
readonly CalculatedFieldType = CalculatedFieldType;
private popoverComponent: TbPopoverComponent<CalculatedFieldArgumentPanelComponent>;
private propagateChange: (argumentsObj: Record<string, CalculatedFieldArgument>) => void = () => {};
@ -105,6 +110,13 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
});
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.calculatedFieldType?.previousValue
&& changes.calculatedFieldType.currentValue !== changes.calculatedFieldType.previousValue) {
this.argumentsFormArray.markAsDirty();
}
}
registerOnChange(fn: (argumentsObj: Record<string, CalculatedFieldArgument>) => void): void {
this.propagateChange = fn;
}
@ -137,6 +149,7 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
calculatedFieldType: this.calculatedFieldType(),
buttonTitle: this.argumentsFormArray.at(index)?.value ? 'action.apply' : 'action.add',
tenantId: this.tenantId,
entityName: this.entityName,
};
this.popoverComponent = this.popoverService.displayPopover(trigger, this.renderer,
this.viewContainerRef, CalculatedFieldArgumentPanelComponent, 'left', false, null,
@ -202,6 +215,7 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
}),
} : {}),
refEntityKey: this.fb.group({
...value.refEntityKey,
type: [{ value: value.refEntityKey.type, disabled: true }],
key: [{ value: value.refEntityKey.key, disabled: true }],
}),

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

@ -69,6 +69,7 @@
formControlName="arguments"
[entityId]="data.entityId"
[tenantId]="data.tenantId"
[entityName]="data.entityName"
[calculatedFieldType]="fieldFormGroup.get('type').value"
/>
</div>
@ -114,7 +115,7 @@
</mat-form-field>
@if (outputFormGroup.get('type').value === OutputType.Attribute) {
<mat-form-field class="flex-1" appearance="outline" subscriptSizing="dynamic">
<mat-label>{{ 'calculated-fields.output-type' | translate }}</mat-label>
<mat-label>{{ 'calculated-fields.attribute-scope' | translate }}</mat-label>
<mat-select formControlName="scope" class="w-full">
<mat-option [value]="AttributeScope.SERVER_SCOPE">
{{ 'calculated-fields.server-attributes' | translate }}

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

@ -59,10 +59,10 @@ export class CalculatedFieldDialogComponent extends DialogComponent<CalculatedFi
}),
});
functionArgs$ = this.configFormGroup.valueChanges
functionArgs$ = this.configFormGroup.get('arguments').valueChanges
.pipe(
startWith(this.data.value?.configuration ?? {}),
map(configuration => Object.keys(configuration.arguments))
startWith(this.data.value?.configuration?.arguments ?? {}),
map(argumentsObj => Object.keys(argumentsObj))
);
readonly OutputTypeTranslations = OutputTypeTranslations;

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

@ -96,7 +96,7 @@
}
</mat-form-field>
</div>
@if (entityFilter.singleEntity.id || entityType === ArgumentEntityType.Current || entityType === ArgumentEntityType.Tenant) {
@if (entityFilter.singleEntity?.id || entityType === ArgumentEntityType.Current || entityType === ArgumentEntityType.Tenant) {
@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>

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

@ -25,7 +25,8 @@ import {
ArgumentType,
ArgumentTypeTranslations,
CalculatedFieldArgumentValue,
CalculatedFieldType
CalculatedFieldType,
getCalculatedFieldCurrentEntityFilter
} from '@shared/models/calculated-field.models';
import { debounceTime, distinctUntilChanged, filter } from 'rxjs/operators';
import { EntityType } from '@shared/models/entity-type.models';
@ -49,6 +50,7 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit {
@Input() argument: CalculatedFieldArgumentValue;
@Input() entityId: EntityId;
@Input() tenantId: string;
@Input() entityName: string;
@Input() calculatedFieldType: CalculatedFieldType;
argumentsDataApplied = output<{ value: CalculatedFieldArgumentValue, index: number }>();
@ -83,6 +85,8 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit {
readonly ArgumentEntityType = ArgumentEntityType;
readonly ArgumentEntityTypeParamsMap = ArgumentEntityTypeParamsMap;
private currentEntityFilter: EntityFilter;
constructor(
private fb: FormBuilder,
private cd: ChangeDetectorRef,
@ -107,6 +111,7 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit {
ngOnInit(): void {
this.argumentFormGroup.patchValue(this.argument, {emitEvent: false});
this.currentEntityFilter = getCalculatedFieldCurrentEntityFilter(this.entityName, this.entityId);
this.updateEntityFilter(this.argument.refEntityId?.entityType, true);
this.toggleByEntityKeyType(this.argument.refEntityKey?.type);
this.setInitialEntityKeyType();
@ -138,27 +143,30 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit {
}
private updateEntityFilter(entityType: ArgumentEntityType = ArgumentEntityType.Current, onInit = false): void {
let entityId: EntityId;
let entityFilter: EntityFilter;
switch (entityType) {
case ArgumentEntityType.Current:
entityId = this.entityId
entityFilter = this.currentEntityFilter;
break;
case ArgumentEntityType.Tenant:
entityId = {
id: this.tenantId,
entityType: EntityType.TENANT
entityFilter = {
type: AliasFilterType.singleEntity,
singleEntity: {
id: this.tenantId,
entityType: EntityType.TENANT
},
};
break;
default:
entityId = this.argumentFormGroup.get('refEntityId').value as unknown as EntityId;
entityFilter = {
type: AliasFilterType.singleEntity,
singleEntity: this.argumentFormGroup.get('refEntityId').value as unknown as EntityId,
};
}
if (!onInit) {
this.argumentFormGroup.get('refEntityKey').get('key').setValue('');
}
this.entityFilter = {
type: AliasFilterType.singleEntity,
singleEntity: entityId,
};
this.entityFilter = entityFilter;
this.cd.markForCheck();
}

4
ui-ngx/src/app/modules/home/pages/asset-profile/asset-profile-tabs.component.html

@ -15,6 +15,10 @@
limitations under the License.
-->
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN && !isEdit"
label="{{ 'entity.type-calculated-fields' | translate }}" #calculatedFieldsTab="matTab">
<tb-calculated-fields-table [active]="calculatedFieldsTab.isActive" [entityId]="entity.id" [entityName]="entity.name"/>
</mat-tab>
<mat-tab *ngIf="entity && !isEdit" #auditLogsTab="matTab"
label="{{ 'audit-log.audit-logs' | translate }}">
<tb-audit-log-table detailsMode="true" [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id"></tb-audit-log-table>

4
ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.html

@ -32,6 +32,10 @@
[entityName]="entity.name">
</tb-attribute-table>
</mat-tab>
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
label="{{ 'entity.type-calculated-fields' | translate }}" #calculatedFieldsTab="matTab">
<tb-calculated-fields-table [active]="calculatedFieldsTab.isActive" [entityId]="entity.id"/>
</mat-tab>
<mat-tab *ngIf="entity"
label="{{ 'alarm.alarms' | translate }}" #alarmsTab="matTab">
<tb-alarm-table [active]="alarmsTab.isActive" [entityId]="entity.id"></tb-alarm-table>

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

@ -69,6 +69,10 @@
</div>
</div>
</mat-tab>
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN && !isEdit"
label="{{ 'entity.type-calculated-fields' | translate }}" #calculatedFieldsTab="matTab">
<tb-calculated-fields-table [active]="calculatedFieldsTab.isActive" [entityId]="entity.id" [entityName]="entity.name"/>
</mat-tab>
<mat-tab *ngIf="entity && !isEdit" #auditLogsTab="matTab"
label="{{ 'audit-log.audit-logs' | translate }}">
<tb-audit-log-table detailsMode="true" [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id"></tb-audit-log-table>

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

@ -20,6 +20,7 @@ import { CalculatedFieldId } from '@shared/models/id/calculated-field-id';
import { EntityId } from '@shared/models/id/entity-id';
import { AttributeScope } from '@shared/models/telemetry/telemetry.models';
import { EntityType } from '@shared/models/entity-type.models';
import { AliasFilterType } from '@shared/models/alias.models';
export interface CalculatedField extends Omit<BaseData<CalculatedFieldId>, 'label'>, HasVersion, HasTenantId {
debugSettings?: EntityDebugSettings;
@ -120,6 +121,7 @@ export interface CalculatedFieldDialogData {
entityId: EntityId;
debugLimitsConfiguration: string;
tenantId: string;
entityName?: string;
}
export interface ArgumentEntityTypeParams {
@ -132,3 +134,23 @@ export const ArgumentEntityTypeParamsMap =new Map<ArgumentEntityType, ArgumentEn
[ArgumentEntityType.Asset, { title: 'calculated-fields.asset-name', entityType: EntityType.ASSET }],
[ArgumentEntityType.Customer, { title: 'calculated-fields.customer-name', entityType: EntityType.CUSTOMER }],
])
export const getCalculatedFieldCurrentEntityFilter = (entityName: string, entityId: EntityId) => {
switch (entityId.entityType) {
case EntityType.ASSET_PROFILE:
return {
assetTypes: [entityName],
type: AliasFilterType.assetType
};
case EntityType.DEVICE_PROFILE:
return {
deviceTypes: [entityName],
type: AliasFilterType.deviceType
};
default:
return {
type: AliasFilterType.singleEntity,
singleEntity: entityId,
};
}
}

Loading…
Cancel
Save