Browse Source

Reworked test arguments and adjustments

pull/12700/head
mpetrov 2 years ago
parent
commit
e850550763
  1. 8
      ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts
  2. 8
      ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts
  3. 30
      ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html
  4. 12
      ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.scss
  5. 79
      ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts
  6. 7
      ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html
  7. 2
      ui-ngx/src/app/shared/components/js-func.component.ts
  8. 2
      ui-ngx/src/app/shared/components/json-object-edit.component.html
  9. 2
      ui-ngx/src/app/shared/components/value-input.component.html
  10. 4
      ui-ngx/src/app/shared/components/value-input.component.ts
  11. 13
      ui-ngx/src/app/shared/models/calculated-field.models.ts
  12. 1
      ui-ngx/src/assets/locale/locale.constant-en_US.json
  13. 13
      ui-ngx/src/styles.scss

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

@ -36,6 +36,7 @@ import { EntityDebugSettingsPanelComponent } from '@home/components/entity/debug
import { CalculatedFieldsService } from '@core/http/calculated-fields.service'; import { CalculatedFieldsService } from '@core/http/calculated-fields.service';
import { catchError, filter, switchMap, tap } from 'rxjs/operators'; import { catchError, filter, switchMap, tap } from 'rxjs/operators';
import { import {
ArgumentType,
CalculatedField, CalculatedField,
CalculatedFieldEventArguments, CalculatedFieldEventArguments,
CalculatedFieldDebugDialogData, CalculatedFieldDebugDialogData,
@ -122,7 +123,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
}, },
{ {
name: this.translate.instant('entity-view.events'), name: this.translate.instant('entity-view.events'),
icon: 'history', icon: 'mdi:clipboard-text-clock',
isEnabled: () => true, isEnabled: () => true,
onAction: (_, entity) => this.openDebugEventsDialog(entity), onAction: (_, entity) => this.openDebugEventsDialog(entity),
}, },
@ -260,7 +261,10 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
private getTestScriptDialog(calculatedField: CalculatedField, argumentsObj?: CalculatedFieldEventArguments, openCalculatedFieldEdit = true): Observable<string> { private getTestScriptDialog(calculatedField: CalculatedField, argumentsObj?: CalculatedFieldEventArguments, openCalculatedFieldEdit = true): Observable<string> {
const resultArguments = Object.keys(calculatedField.configuration.arguments).reduce((acc, key) => { const resultArguments = Object.keys(calculatedField.configuration.arguments).reduce((acc, key) => {
acc[key] = isObject(argumentsObj) && argumentsObj.hasOwnProperty(key) ? argumentsObj[key] : ''; const type = calculatedField.configuration.arguments[key].refEntityKey.type;
acc[key] = isObject(argumentsObj) && argumentsObj.hasOwnProperty(key)
? { ...argumentsObj[key], type }
: type === ArgumentType.Rolling ? { values: [], type } : { value: '', type, ts: new Date().getTime() };
return acc; return acc;
}, {}); }, {});
return this.dialog.open<CalculatedFieldScriptTestDialogComponent, CalculatedFieldTestScriptDialogData, string>(CalculatedFieldScriptTestDialogComponent, return this.dialog.open<CalculatedFieldScriptTestDialogComponent, CalculatedFieldTestScriptDialogData, string>(CalculatedFieldScriptTestDialogComponent,

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

@ -33,7 +33,6 @@ import {
NG_VALUE_ACCESSOR, NG_VALUE_ACCESSOR,
ValidationErrors, ValidationErrors,
Validator, Validator,
Validators
} from '@angular/forms'; } from '@angular/forms';
import { import {
ArgumentEntityType, ArgumentEntityType,
@ -50,7 +49,6 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { EntityId } from '@shared/models/id/entity-id'; import { EntityId } from '@shared/models/id/entity-id';
import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models'; import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models';
import { isDefinedAndNotNull } from '@core/utils'; import { isDefinedAndNotNull } from '@core/utils';
import { charsWithNumRegex } from '@shared/models/regex.constants';
import { TbPopoverComponent } from '@shared/components/popover.component'; import { TbPopoverComponent } from '@shared/components/popover.component';
@Component({ @Component({
@ -143,10 +141,10 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
buttonTitle: this.argumentsFormArray.at(index)?.value ? 'action.apply' : 'action.add', buttonTitle: this.argumentsFormArray.at(index)?.value ? 'action.apply' : 'action.add',
tenantId: this.tenantId, tenantId: this.tenantId,
entityName: this.entityName, entityName: this.entityName,
usedArgumentNames: this.argumentsFormArray.value.map(({ argumentName }) => argumentName).filter(name => name !== argumentObj.argumentName), usedArgumentNames: this.argumentsFormArray.getRawValue().map(({ argumentName }) => argumentName).filter(name => name !== argumentObj.argumentName),
}; };
this.popoverComponent = this.popoverService.displayPopover(trigger, this.renderer, this.popoverComponent = this.popoverService.displayPopover(trigger, this.renderer,
this.viewContainerRef, CalculatedFieldArgumentPanelComponent, 'left', false, null, this.viewContainerRef, CalculatedFieldArgumentPanelComponent, index ? 'left' : 'right', false, null,
ctx, ctx,
{}, {},
{}, {}, true); {}, {}, true);
@ -201,7 +199,7 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
private getArgumentFormGroup(value: CalculatedFieldArgumentValue): FormGroup { private getArgumentFormGroup(value: CalculatedFieldArgumentValue): FormGroup {
return this.fb.group({ return this.fb.group({
...value, ...value,
argumentName: [value.argumentName, [Validators.required, Validators.maxLength(255), Validators.pattern(charsWithNumRegex)]], argumentName: [{ value: value.argumentName, disabled: true }],
...(value.refEntityId ? { ...(value.refEntityId ? {
refEntityId: this.fb.group({ refEntityId: this.fb.group({
entityType: [{ value: value.refEntityId.entityType, disabled: true }], entityType: [{ value: value.refEntityId.entityType, disabled: true }],

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

@ -19,16 +19,38 @@
<div>{{ 'calculated-fields.arguments' | translate }}</div> <div>{{ 'calculated-fields.arguments' | translate }}</div>
<div class="tb-form-table"> <div class="tb-form-table">
<div class="tb-form-table-header"> <div class="tb-form-table-header">
<div class="tb-form-table-header-cell w-1/4" tbTruncateWithTooltip>{{ 'calculated-fields.argument-name' | translate }}</div> <div class="tb-form-table-header-cell w-1/6">{{ 'common.name' | translate }}</div>
<div class="tb-form-table-header-cell flex-1">{{ 'common.value' | translate }}</div> <div class="tb-form-table-header-cell w-1/5 lt-sm:hidden">{{ 'common.type' | translate }}</div>
<div class="tb-form-table-header-cell flex-1">{{ 'common.data' | translate }}</div>
</div> </div>
<div class="tb-form-table-body"> <div class="tb-form-table-body">
@for (group of argumentsFormArray.controls; track group) { @for (group of argumentsFormArray.controls; track group) {
<div [formGroup]="group" class="tb-form-table-row"> <div [formGroup]="group" class="tb-form-table-row">
<mat-form-field appearance="outline" class="tb-inline-field w-1/4" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="tb-inline-field w-1/6" subscriptSizing="dynamic">
<input matInput formControlName="argumentName" placeholder="{{ 'action.set' | translate }}"> <input matInput formControlName="argumentName" placeholder="{{ 'action.set' | translate }}">
</mat-form-field> </mat-form-field>
<tb-value-input class="argument-value flex-1" [required]="false" [shortBooleanField]="true" formControlName="value"/> <mat-form-field appearance="outline" class="tb-inline-field w-1/5 lt-sm:hidden" subscriptSizing="dynamic">
<mat-select [value]="group.get('type').value" formControlName="type">
<mat-option [value]="group.get('type').value">
{{ ArgumentTypeTranslations.get(group.get('type').value) | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<div class="flex flex-1 items-center gap-2">
@if (group.get('type').value === ArgumentType.Rolling) {
<mat-form-field appearance="outline" subscriptSizing="dynamic" class="tb-inline-field flex-1">
<input matInput tb-json-to-string name="values" formControlName="values" placeholder="{{ 'value.json-value' | translate }}*"/>
</mat-form-field>
} @else {
<mat-form-field appearance="outline" class="tb-inline-field" subscriptSizing="dynamic">
<input matInput formControlName="ts" type="number" placeholder="{{ 'action.set' | translate }}">
</mat-form-field>
<tb-value-input class="argument-value min-w-72 flex-1" [required]="false" [hideJsonEdit]="true" [shortBooleanField]="true" formControlName="value"/>
}
<button mat-icon-button class="tb-mat-32" (click)="openEditJSONDialog(group)">
<mat-icon class="tb-mat-20">open_in_new</mat-icon>
</button>
</div>
</div> </div>
} }
</div> </div>

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

@ -15,14 +15,18 @@
*/ */
@use '../../../../../../../scss/constants' as constants; @use '../../../../../../../scss/constants' as constants;
:host {
.tb-form-table {
min-width: 700px;
}
}
:host::ng-deep { :host::ng-deep {
.tb-form-table-row { .tb-form-table-row {
.argument-value { .argument-value {
.tb-value-type.row { .tb-value-type.row {
@media #{constants.$mat-lt-sm} { width: 120px;
width: 100px; min-width: 120px;
min-width: 100px;
}
} }
} }
} }

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

@ -26,6 +26,22 @@ import {
} from '@angular/forms'; } from '@angular/forms';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { entityTypeTranslations } from '@shared/models/entity-type.models';
import {
ArgumentType,
ArgumentTypeTranslations,
CalculatedFieldArgumentEventValue,
CalculatedFieldRollingTelemetryArgumentValue,
CalculatedFieldSingleArgumentValue,
CalculatedFieldEventArguments,
CalculatedFieldType
} from '@shared/models/calculated-field.models';
import {
JsonObjectEditDialogComponent,
JsonObjectEditDialogData
} from '@shared/components/dialog/json-object-edit-dialog.component';
import { filter } from 'rxjs/operators';
import { MatDialog } from '@angular/material/dialog';
@Component({ @Component({
selector: 'tb-calculated-field-test-arguments', selector: 'tb-calculated-field-test-arguments',
@ -49,29 +65,35 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme
argumentsFormArray = this.fb.array<FormGroup>([]); argumentsFormArray = this.fb.array<FormGroup>([]);
private propagateChange: (value: { argumentName: string; value: unknown }) => void; readonly entityTypeTranslations = entityTypeTranslations;
readonly ArgumentTypeTranslations = ArgumentTypeTranslations;
readonly ArgumentType = ArgumentType;
readonly CalculatedFieldType = CalculatedFieldType;
private propagateChange: (value: CalculatedFieldEventArguments) => void;
constructor(private fb: FormBuilder) { constructor(private fb: FormBuilder, private dialog: MatDialog) {
super(); super();
this.argumentsFormArray.valueChanges this.argumentsFormArray.valueChanges
.pipe(takeUntilDestroyed()) .pipe(takeUntilDestroyed())
.subscribe(() => this.propagateChange(this.getValue())); .subscribe(() => this.propagateChange(this.getValue()));
} }
registerOnChange(propagateChange: (value: { argumentName: string; value: unknown }) => void): void { registerOnChange(propagateChange: (value: CalculatedFieldEventArguments) => void): void {
this.propagateChange = propagateChange; this.propagateChange = propagateChange;
} }
registerOnTouched(_): void { registerOnTouched(_): void {
} }
writeValue(argumentsObj: Record<string, unknown>): void { writeValue(argumentsObj: CalculatedFieldEventArguments): void {
this.argumentsFormArray.clear(); this.argumentsFormArray.clear();
Object.keys(argumentsObj).forEach(key => { Object.keys(argumentsObj).forEach(key => {
this.argumentsFormArray.push(this.fb.group({ const value = { ...argumentsObj[key], argumentName: key } as CalculatedFieldArgumentEventValue;
argumentName: [{ value: key, disabled: true}], this.argumentsFormArray.push((value).type === ArgumentType.Rolling
value: [argumentsObj[key]] ? this.getRollingArgumentFormGroup(value as CalculatedFieldRollingTelemetryArgumentValue)
}) as FormGroup, {emitEvent: false}); : this.getSimpleArgumentFormGroup(value as CalculatedFieldSingleArgumentValue),
{emitEvent: false});
}); });
} }
@ -79,11 +101,44 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme
return this.argumentsFormArray.valid ? null : { arguments: { valid: false } }; return this.argumentsFormArray.valid ? null : { arguments: { valid: false } };
} }
private getValue(): { argumentName: string; value: unknown } { private getSimpleArgumentFormGroup({ argumentName, type, ts, value }: CalculatedFieldSingleArgumentValue): FormGroup {
return this.fb.group({
argumentName: [{ value: argumentName, disabled: true}],
type: [{ value: type , disabled: true }],
ts: [ts],
value: [value]
}) as FormGroup;
}
private getRollingArgumentFormGroup({ argumentName, type, timewindow, values }: CalculatedFieldRollingTelemetryArgumentValue): FormGroup {
return this.fb.group({
...timewindow ?? {},
argumentName: [{ value: argumentName, disabled: true }],
type: [{ value: type , disabled: true }],
values: [values]
}) as FormGroup;
}
openEditJSONDialog(group: FormGroup): void {
this.dialog.open<JsonObjectEditDialogComponent, JsonObjectEditDialogData, CalculatedFieldArgumentEventValue>(JsonObjectEditDialogComponent, {
disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog', 'tb-dialog-min-w-700', 'tb-dialog-h-fill'],
data: {
jsonValue: group.value,
required: true
}
}).afterClosed()
.pipe(filter(Boolean))
.subscribe(result => group.get('type').value === ArgumentType.Rolling
? group.patchValue({ timewindow: (result as CalculatedFieldRollingTelemetryArgumentValue).timewindow, values: (result as CalculatedFieldRollingTelemetryArgumentValue).values })
: group.patchValue({ ts: (result as CalculatedFieldSingleArgumentValue).ts, value: (result as CalculatedFieldSingleArgumentValue).value }) );
}
private getValue(): CalculatedFieldEventArguments {
return this.argumentsFormArray.getRawValue().reduce((acc, rowItem) => { return this.argumentsFormArray.getRawValue().reduce((acc, rowItem) => {
const { argumentName, value } = rowItem; const { argumentName, type, ...value } = rowItem;
acc[argumentName] = value; acc[argumentName] = { ...value };
return acc; return acc;
}, {}) as { argumentName: string; value: unknown }; }, {});
} }
} }

7
ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html

@ -15,7 +15,7 @@
limitations under the License. limitations under the License.
--> -->
<form [formGroup]="jsonFormGroup" (ngSubmit)="add()" style="min-width: 400px;"> <form [formGroup]="jsonFormGroup" (ngSubmit)="add()" style="min-width: 400px;" class="h-full">
<mat-toolbar class="flex flex-row" color="primary"> <mat-toolbar class="flex flex-row" color="primary">
<h2>{{ title }}</h2> <h2>{{ title }}</h2>
<span class="flex-1"></span> <span class="flex-1"></span>
@ -28,10 +28,11 @@
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async"> <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
</mat-progress-bar> </mat-progress-bar>
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div> <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<div mat-dialog-content> <div mat-dialog-content class="flex-1">
<fieldset [disabled]="isLoading$ | async"> <fieldset [disabled]="isLoading$ | async" class="h-full">
<tb-json-object-edit <tb-json-object-edit
formControlName="json" formControlName="json"
class="block h-full"
label="{{ 'value.json-value' | translate }}" label="{{ 'value.json-value' | translate }}"
[jsonRequired]="required" [jsonRequired]="required"
[fillHeight]="false"> [fillHeight]="false">

2
ui-ngx/src/app/shared/components/js-func.component.ts

@ -184,7 +184,7 @@ export class JsFuncComponent implements OnInit, OnChanges, OnDestroy, ControlVal
this.updateFunctionArgsString(); this.updateFunctionArgsString();
this.updateFunctionLabel(); this.updateFunctionLabel();
} }
if (changes.editorCompleter) { if (changes.editorCompleter?.previousValue) {
this.updateCompleters(); this.updateCompleters();
} }
} }

2
ui-ngx/src/app/shared/components/json-object-edit.component.html

@ -15,7 +15,7 @@
limitations under the License. limitations under the License.
--> -->
<div class="flex flex-col" style="background: #fff;" [class.fill-height]="fillHeight" <div class="flex h-full flex-col" style="background: #fff;" [class.fill-height]="fillHeight"
tb-fullscreen tb-fullscreen
[fullscreen]="fullscreen" (fullscreenChanged)="onFullscreen()"> [fullscreen]="fullscreen" (fullscreenChanged)="onFullscreen()">
<div class="tb-json-object-toolbar flex flex-row items-center justify-start"> <div class="tb-json-object-toolbar flex flex-row items-center justify-start">

2
ui-ngx/src/app/shared/components/value-input.component.html

@ -93,7 +93,7 @@
warning warning
</mat-icon> </mat-icon>
</mat-form-field> </mat-form-field>
<button mat-icon-button class="tb-mat-32" (click)="openEditJSONDialog($event)"> <button *ngIf="!hideJsonEdit" mat-icon-button class="tb-mat-32" (click)="openEditJSONDialog($event)">
<mat-icon class="tb-mat-20">open_in_new</mat-icon> <mat-icon class="tb-mat-20">open_in_new</mat-icon>
</button> </button>
</div> </div>

4
ui-ngx/src/app/shared/components/value-input.component.ts

@ -85,6 +85,10 @@ export class ValueInputComponent implements OnInit, OnDestroy, OnChanges, Contro
@coerceBoolean() @coerceBoolean()
required = true; required = true;
@Input()
@coerceBoolean()
hideJsonEdit = false;
@Input() @Input()
layout: ValueInputLayout | Layout = 'row'; layout: ValueInputLayout | Layout = 'row';

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

@ -154,7 +154,7 @@ export interface CalculatedFieldTestScriptInputParams {
} }
export interface CalculatedFieldTestScriptDialogData extends CalculatedFieldTestScriptInputParams { export interface CalculatedFieldTestScriptDialogData extends CalculatedFieldTestScriptInputParams {
argumentsEditorCompleter: TbEditorCompleter argumentsEditorCompleter: TbEditorCompleter;
openCalculatedFieldEdit?: boolean; openCalculatedFieldEdit?: boolean;
} }
@ -189,17 +189,22 @@ export const getCalculatedFieldCurrentEntityFilter = (entityName: string, entity
} }
} }
export interface CalculatedFieldAttributeArgumentValue<ValueType = unknown> { export interface CalculatedFieldArgumentValueBase {
argumentName: string;
type: ArgumentType;
}
export interface CalculatedFieldAttributeArgumentValue<ValueType = unknown> extends CalculatedFieldArgumentValueBase {
ts: number; ts: number;
value: ValueType; value: ValueType;
} }
export interface CalculatedFieldLatestTelemetryArgumentValue<ValueType = unknown> { export interface CalculatedFieldLatestTelemetryArgumentValue<ValueType = unknown> extends CalculatedFieldArgumentValueBase {
ts: number; ts: number;
value: ValueType; value: ValueType;
} }
export interface CalculatedFieldRollingTelemetryArgumentValue<ValueType = unknown> { export interface CalculatedFieldRollingTelemetryArgumentValue<ValueType = unknown> extends CalculatedFieldArgumentValueBase {
timewindow: { startTs: number; endTs: number; limit: number }; timewindow: { startTs: number; endTs: number; limit: number };
values: CalculatedFieldSingleArgumentValue<ValueType>[]; values: CalculatedFieldSingleArgumentValue<ValueType>[];
} }

1
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -1100,6 +1100,7 @@
"general": "General", "general": "General",
"username": "Username", "username": "Username",
"password": "Password", "password": "Password",
"data": "Data",
"enter-username": "Enter username", "enter-username": "Enter username",
"enter-password": "Enter password", "enter-password": "Enter password",
"enter-search": "Enter search", "enter-search": "Enter search",

13
ui-ngx/src/styles.scss

@ -1058,6 +1058,19 @@ pre.tb-highlight {
display: block; display: block;
} }
} }
@for $i from 1 through 10 {
&-min-w-#{$i * 100} {
@media screen and (min-width: #{$i * 100}px) {
--mat-dialog-container-min-width: #{$i * 100}px;
}
}
}
&-h-fill {
height: 65vh;
}
} }
.tb-fullscreen-dialog-gt-xs { .tb-fullscreen-dialog-gt-xs {

Loading…
Cancel
Save