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 { catchError, filter, switchMap, tap } from 'rxjs/operators';
import {
ArgumentType,
CalculatedField,
CalculatedFieldEventArguments,
CalculatedFieldDebugDialogData,
@ -122,7 +123,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
},
{
name: this.translate.instant('entity-view.events'),
icon: 'history',
icon: 'mdi:clipboard-text-clock',
isEnabled: () => true,
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> {
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 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,
ValidationErrors,
Validator,
Validators
} from '@angular/forms';
import {
ArgumentEntityType,
@ -50,7 +49,6 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { EntityId } from '@shared/models/id/entity-id';
import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models';
import { isDefinedAndNotNull } from '@core/utils';
import { charsWithNumRegex } from '@shared/models/regex.constants';
import { TbPopoverComponent } from '@shared/components/popover.component';
@Component({
@ -143,10 +141,10 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
buttonTitle: this.argumentsFormArray.at(index)?.value ? 'action.apply' : 'action.add',
tenantId: this.tenantId,
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.viewContainerRef, CalculatedFieldArgumentPanelComponent, 'left', false, null,
this.viewContainerRef, CalculatedFieldArgumentPanelComponent, index ? 'left' : 'right', false, null,
ctx,
{},
{}, {}, true);
@ -201,7 +199,7 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
private getArgumentFormGroup(value: CalculatedFieldArgumentValue): FormGroup {
return this.fb.group({
...value,
argumentName: [value.argumentName, [Validators.required, Validators.maxLength(255), Validators.pattern(charsWithNumRegex)]],
argumentName: [{ value: value.argumentName, disabled: true }],
...(value.refEntityId ? {
refEntityId: this.fb.group({
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 class="tb-form-table">
<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 flex-1">{{ 'common.value' | translate }}</div>
<div class="tb-form-table-header-cell w-1/6">{{ 'common.name' | 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 class="tb-form-table-body">
@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/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 }}">
</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>

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;
:host {
.tb-form-table {
min-width: 700px;
}
}
:host::ng-deep {
.tb-form-table-row {
.argument-value {
.tb-value-type.row {
@media #{constants.$mat-lt-sm} {
width: 100px;
min-width: 100px;
}
width: 120px;
min-width: 120px;
}
}
}

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';
import { PageComponent } from '@shared/components/page.component';
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({
selector: 'tb-calculated-field-test-arguments',
@ -49,29 +65,35 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme
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();
this.argumentsFormArray.valueChanges
.pipe(takeUntilDestroyed())
.subscribe(() => this.propagateChange(this.getValue()));
}
registerOnChange(propagateChange: (value: { argumentName: string; value: unknown }) => void): void {
registerOnChange(propagateChange: (value: CalculatedFieldEventArguments) => void): void {
this.propagateChange = propagateChange;
}
registerOnTouched(_): void {
}
writeValue(argumentsObj: Record<string, unknown>): void {
writeValue(argumentsObj: CalculatedFieldEventArguments): void {
this.argumentsFormArray.clear();
Object.keys(argumentsObj).forEach(key => {
this.argumentsFormArray.push(this.fb.group({
argumentName: [{ value: key, disabled: true}],
value: [argumentsObj[key]]
}) as FormGroup, {emitEvent: false});
const value = { ...argumentsObj[key], argumentName: key } as CalculatedFieldArgumentEventValue;
this.argumentsFormArray.push((value).type === ArgumentType.Rolling
? this.getRollingArgumentFormGroup(value as CalculatedFieldRollingTelemetryArgumentValue)
: 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 } };
}
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) => {
const { argumentName, value } = rowItem;
acc[argumentName] = value;
const { argumentName, type, ...value } = rowItem;
acc[argumentName] = { ...value };
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.
-->
<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">
<h2>{{ title }}</h2>
<span class="flex-1"></span>
@ -28,10 +28,11 @@
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
</mat-progress-bar>
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<div mat-dialog-content>
<fieldset [disabled]="isLoading$ | async">
<div mat-dialog-content class="flex-1">
<fieldset [disabled]="isLoading$ | async" class="h-full">
<tb-json-object-edit
formControlName="json"
class="block h-full"
label="{{ 'value.json-value' | translate }}"
[jsonRequired]="required"
[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.updateFunctionLabel();
}
if (changes.editorCompleter) {
if (changes.editorCompleter?.previousValue) {
this.updateCompleters();
}
}

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

@ -15,7 +15,7 @@
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
[fullscreen]="fullscreen" (fullscreenChanged)="onFullscreen()">
<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
</mat-icon>
</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>
</button>
</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()
required = true;
@Input()
@coerceBoolean()
hideJsonEdit = false;
@Input()
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 {
argumentsEditorCompleter: TbEditorCompleter
argumentsEditorCompleter: TbEditorCompleter;
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;
value: ValueType;
}
export interface CalculatedFieldLatestTelemetryArgumentValue<ValueType = unknown> {
export interface CalculatedFieldLatestTelemetryArgumentValue<ValueType = unknown> extends CalculatedFieldArgumentValueBase {
ts: number;
value: ValueType;
}
export interface CalculatedFieldRollingTelemetryArgumentValue<ValueType = unknown> {
export interface CalculatedFieldRollingTelemetryArgumentValue<ValueType = unknown> extends CalculatedFieldArgumentValueBase {
timewindow: { startTs: number; endTs: number; limit: number };
values: CalculatedFieldSingleArgumentValue<ValueType>[];
}

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

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

13
ui-ngx/src/styles.scss

@ -1058,6 +1058,19 @@ pre.tb-highlight {
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 {

Loading…
Cancel
Save