Calculated adjustments
This commit is contained in:
parent
7d57cde6fa
commit
8c7c54b554
@ -258,8 +258,15 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
|
|||||||
}
|
}
|
||||||
|
|
||||||
private importCalculatedField(): void {
|
private importCalculatedField(): void {
|
||||||
this.importExportService.importCalculatedField(this.entityId)
|
this.importExportService.openCalculatedFieldImportDialog()
|
||||||
.pipe(filter(Boolean), takeUntilDestroyed(this.destroyRef))
|
.pipe(
|
||||||
|
filter(Boolean),
|
||||||
|
switchMap(calculatedField => this.getCalculatedFieldDialog(calculatedField, 'action.add')),
|
||||||
|
filter(Boolean),
|
||||||
|
switchMap(calculatedField => this.calculatedFieldsService.saveCalculatedField(calculatedField)),
|
||||||
|
filter(Boolean),
|
||||||
|
takeUntilDestroyed(this.destroyRef)
|
||||||
|
)
|
||||||
.subscribe(() => this.updateData());
|
.subscribe(() => this.updateData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -97,7 +97,7 @@
|
|||||||
matTooltipPosition="above">
|
matTooltipPosition="above">
|
||||||
<mat-icon
|
<mat-icon
|
||||||
[matBadgeHidden]="!(argument.refEntityKey.type === ArgumentType.Rolling
|
[matBadgeHidden]="!(argument.refEntityKey.type === ArgumentType.Rolling
|
||||||
&& calculatedFieldType === CalculatedFieldType.SIMPLE)"
|
&& calculatedFieldType === CalculatedFieldType.SIMPLE) && !entityNameErrorSet.has(argument.refEntityId?.id)"
|
||||||
matBadgeColor="warn"
|
matBadgeColor="warn"
|
||||||
matBadgeSize="small"
|
matBadgeSize="small"
|
||||||
matBadge="*"
|
matBadge="*"
|
||||||
|
|||||||
@ -58,6 +58,8 @@ import { MatSort } from '@angular/material/sort';
|
|||||||
import { getCurrentAuthState } from '@core/auth/auth.selectors';
|
import { getCurrentAuthState } from '@core/auth/auth.selectors';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { AppState } from '@core/core.state';
|
import { AppState } from '@core/core.state';
|
||||||
|
import { catchError } from 'rxjs/operators';
|
||||||
|
import { NEVER } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-calculated-field-arguments-table',
|
selector: 'tb-calculated-field-arguments-table',
|
||||||
@ -88,6 +90,7 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
|
|||||||
errorText = '';
|
errorText = '';
|
||||||
argumentsFormArray = this.fb.array<AbstractControl>([]);
|
argumentsFormArray = this.fb.array<AbstractControl>([]);
|
||||||
entityNameMap = new Map<string, string>();
|
entityNameMap = new Map<string, string>();
|
||||||
|
entityNameErrorSet = new Set<string>();
|
||||||
sortOrder = { direction: 'asc', property: '' };
|
sortOrder = { direction: 'asc', property: '' };
|
||||||
dataSource = new CalculatedFieldArgumentDatasource();
|
dataSource = new CalculatedFieldArgumentDatasource();
|
||||||
|
|
||||||
@ -168,6 +171,7 @@ 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,
|
||||||
|
entityHasError: this.entityNameErrorSet.has(argument.refEntityId?.id),
|
||||||
usedArgumentNames: this.argumentsFormArray.value.map(({ argumentName }) => argumentName).filter(name => name !== argument.argumentName),
|
usedArgumentNames: this.argumentsFormArray.value.map(({ argumentName }) => argumentName).filter(name => name !== argument.argumentName),
|
||||||
};
|
};
|
||||||
this.popoverComponent = this.popoverService.displayPopover(trigger, this.renderer,
|
this.popoverComponent = this.popoverService.displayPopover(trigger, this.renderer,
|
||||||
@ -198,6 +202,8 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
|
|||||||
if (this.calculatedFieldType === CalculatedFieldType.SIMPLE
|
if (this.calculatedFieldType === CalculatedFieldType.SIMPLE
|
||||||
&& this.argumentsFormArray.controls.some(control => control.value.refEntityKey.type === ArgumentType.Rolling)) {
|
&& this.argumentsFormArray.controls.some(control => control.value.refEntityKey.type === ArgumentType.Rolling)) {
|
||||||
this.errorText = 'calculated-fields.hint.arguments-simple-with-rolling';
|
this.errorText = 'calculated-fields.hint.arguments-simple-with-rolling';
|
||||||
|
} else if (this.entityNameErrorSet.size) {
|
||||||
|
this.errorText = 'calculated-fields.hint.arguments-entity-not-found';
|
||||||
} else if (!this.argumentsFormArray.controls.length) {
|
} else if (!this.argumentsFormArray.controls.length) {
|
||||||
this.errorText = 'calculated-fields.hint.arguments-empty';
|
this.errorText = 'calculated-fields.hint.arguments-empty';
|
||||||
} else {
|
} else {
|
||||||
@ -234,11 +240,18 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces
|
|||||||
}
|
}
|
||||||
|
|
||||||
private updateEntityNameMap(value: CalculatedFieldArgumentValue[]): void {
|
private updateEntityNameMap(value: CalculatedFieldArgumentValue[]): void {
|
||||||
|
this.entityNameErrorSet.clear();
|
||||||
value.forEach(({ refEntityId = {}}) => {
|
value.forEach(({ refEntityId = {}}) => {
|
||||||
if (refEntityId.id && !this.entityNameMap.has(refEntityId.id)) {
|
if (refEntityId.id && !this.entityNameMap.has(refEntityId.id)) {
|
||||||
const { id, entityType } = refEntityId as EntityId;
|
const { id, entityType } = refEntityId as EntityId;
|
||||||
this.entityService.getEntity(entityType as EntityType, id, { ignoreLoading: true, ignoreErrors: true })
|
this.entityService.getEntity(entityType as EntityType, id, { ignoreLoading: true, ignoreErrors: true })
|
||||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
.pipe(
|
||||||
|
catchError(() => {
|
||||||
|
this.entityNameErrorSet.add(id);
|
||||||
|
return NEVER;
|
||||||
|
}),
|
||||||
|
takeUntilDestroyed(this.destroyRef)
|
||||||
|
)
|
||||||
.subscribe(entity => this.entityNameMap.set(id, entity.name));
|
.subscribe(entity => this.entityNameMap.set(id, entity.name));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import { Store } from '@ngrx/store';
|
|||||||
import { AppState } from '@core/core.state';
|
import { AppState } from '@core/core.state';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { DialogComponent } from '@shared/components/dialog.component';
|
import { DialogComponent } from '@shared/components/dialog.component';
|
||||||
import { CalculatedFieldEventBody, DebugEventType, EventType } from '@shared/models/event.models';
|
import { CalculatedFieldEventBody, DebugEventType, Event, EventType } from '@shared/models/event.models';
|
||||||
import { EventTableComponent } from '@home/components/event/event-table.component';
|
import { EventTableComponent } from '@home/components/event/event-table.component';
|
||||||
import { CalculatedFieldDebugDialogData, CalculatedFieldType } from '@shared/models/calculated-field.models';
|
import { CalculatedFieldDebugDialogData, CalculatedFieldType } from '@shared/models/calculated-field.models';
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ export class CalculatedFieldDebugDialogComponent extends DialogComponent<Calcula
|
|||||||
|
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
this.eventsTable.entitiesTable.updateData();
|
this.eventsTable.entitiesTable.updateData();
|
||||||
this.eventsTable.entitiesTable.cellActionDescriptors[0].isEnabled = () => this.data.value.type === CalculatedFieldType.SCRIPT;
|
this.eventsTable.entitiesTable.cellActionDescriptors[0].isEnabled = (event => this.data.value.type === CalculatedFieldType.SCRIPT && !!(event as Event).body.arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel(): void {
|
cancel(): void {
|
||||||
|
|||||||
@ -82,6 +82,7 @@
|
|||||||
<div class="fixed-title-width tb-required">{{ ArgumentEntityTypeParamsMap.get(entityType).title | translate }}</div>
|
<div class="fixed-title-width tb-required">{{ ArgumentEntityTypeParamsMap.get(entityType).title | translate }}</div>
|
||||||
<tb-entity-autocomplete
|
<tb-entity-autocomplete
|
||||||
class="flex flex-1"
|
class="flex flex-1"
|
||||||
|
#entityAutocomplete
|
||||||
formControlName="id"
|
formControlName="id"
|
||||||
inlineField
|
inlineField
|
||||||
[placeholder]="'action.set' | translate"
|
[placeholder]="'action.set' | translate"
|
||||||
@ -165,7 +166,7 @@
|
|||||||
</div>
|
</div>
|
||||||
} @else {
|
} @else {
|
||||||
<div class="tb-form-row">
|
<div class="tb-form-row">
|
||||||
<div class="fixed-title-width">{{ 'calculated-fields.time-window' | translate }}</div>
|
<div class="fixed-title-width tb-required">{{ 'calculated-fields.time-window' | translate }}</div>
|
||||||
<tb-timeinterval
|
<tb-timeinterval
|
||||||
subscriptSizing="dynamic"
|
subscriptSizing="dynamic"
|
||||||
appearance="outline"
|
appearance="outline"
|
||||||
@ -175,7 +176,7 @@
|
|||||||
</div>
|
</div>
|
||||||
@if (maxDataPointsPerRollingArg) {
|
@if (maxDataPointsPerRollingArg) {
|
||||||
<div class="tb-form-row limit-field-row">
|
<div class="tb-form-row limit-field-row">
|
||||||
<div class="fixed-title-width">{{ 'calculated-fields.limit' | translate }}</div>
|
<div class="fixed-title-width tb-required">{{ 'calculated-fields.limit' | translate }}</div>
|
||||||
<div class="limit-slider-container flex w-full flex-1 flex-row items-center justify-start">
|
<div class="limit-slider-container flex w-full flex-1 flex-row items-center justify-start">
|
||||||
<mat-slider class="flex-1" min="1" max="{{maxDataPointsPerRollingArg}}">
|
<mat-slider class="flex-1" min="1" max="{{maxDataPointsPerRollingArg}}">
|
||||||
<input matSliderThumb formControlName="limit" [value]="argumentFormGroup.get('limit').value"/>
|
<input matSliderThumb formControlName="limit" [value]="argumentFormGroup.get('limit').value"/>
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
/// limitations under the License.
|
/// limitations under the License.
|
||||||
///
|
///
|
||||||
|
|
||||||
import { ChangeDetectorRef, Component, Input, OnInit, output } from '@angular/core';
|
import { AfterViewInit, ChangeDetectorRef, Component, Input, OnInit, output, ViewChild } from '@angular/core';
|
||||||
import { TbPopoverComponent } from '@shared/components/popover.component';
|
import { TbPopoverComponent } from '@shared/components/popover.component';
|
||||||
import { FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
|
import { FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
|
||||||
import { charsWithNumRegex, oneSpaceInsideRegex } from '@shared/models/regex.constants';
|
import { charsWithNumRegex, oneSpaceInsideRegex } from '@shared/models/regex.constants';
|
||||||
@ -41,13 +41,14 @@ import { MINUTE } from '@shared/models/time/time.models';
|
|||||||
import { getCurrentAuthState } from '@core/auth/auth.selectors';
|
import { getCurrentAuthState } from '@core/auth/auth.selectors';
|
||||||
import { AppState } from '@core/core.state';
|
import { AppState } from '@core/core.state';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
|
import { EntityAutocompleteComponent } from '@shared/components/entity/entity-autocomplete.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-calculated-field-argument-panel',
|
selector: 'tb-calculated-field-argument-panel',
|
||||||
templateUrl: './calculated-field-argument-panel.component.html',
|
templateUrl: './calculated-field-argument-panel.component.html',
|
||||||
styleUrls: ['./calculated-field-argument-panel.component.scss']
|
styleUrls: ['./calculated-field-argument-panel.component.scss']
|
||||||
})
|
})
|
||||||
export class CalculatedFieldArgumentPanelComponent implements OnInit {
|
export class CalculatedFieldArgumentPanelComponent implements OnInit, AfterViewInit {
|
||||||
|
|
||||||
@Input() buttonTitle: string;
|
@Input() buttonTitle: string;
|
||||||
@Input() index: number;
|
@Input() index: number;
|
||||||
@ -55,9 +56,12 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit {
|
|||||||
@Input() entityId: EntityId;
|
@Input() entityId: EntityId;
|
||||||
@Input() tenantId: string;
|
@Input() tenantId: string;
|
||||||
@Input() entityName: string;
|
@Input() entityName: string;
|
||||||
|
@Input() entityHasError: boolean;
|
||||||
@Input() calculatedFieldType: CalculatedFieldType;
|
@Input() calculatedFieldType: CalculatedFieldType;
|
||||||
@Input() usedArgumentNames: string[];
|
@Input() usedArgumentNames: string[];
|
||||||
|
|
||||||
|
@ViewChild('entityAutocomplete') entityAutocomplete: EntityAutocompleteComponent;
|
||||||
|
|
||||||
argumentsDataApplied = output<{ value: CalculatedFieldArgumentValue, index: number }>();
|
argumentsDataApplied = output<{ value: CalculatedFieldArgumentValue, index: number }>();
|
||||||
|
|
||||||
readonly maxDataPointsPerRollingArg = getCurrentAuthState(this.store).maxDataPointsPerRollingArg;
|
readonly maxDataPointsPerRollingArg = getCurrentAuthState(this.store).maxDataPointsPerRollingArg;
|
||||||
@ -75,8 +79,8 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit {
|
|||||||
scope: [{ value: AttributeScope.SERVER_SCOPE, disabled: true }, [Validators.required]],
|
scope: [{ value: AttributeScope.SERVER_SCOPE, disabled: true }, [Validators.required]],
|
||||||
}),
|
}),
|
||||||
defaultValue: ['', [Validators.pattern(oneSpaceInsideRegex)]],
|
defaultValue: ['', [Validators.pattern(oneSpaceInsideRegex)]],
|
||||||
limit: [{ value: this.defaultLimit, disabled: !this.maxDataPointsPerRollingArg }],
|
limit: [{ value: this.defaultLimit, disabled: !this.maxDataPointsPerRollingArg }, [Validators.required, Validators.min(1), Validators.max(this.maxDataPointsPerRollingArg)]],
|
||||||
timeWindow: [MINUTE * 15],
|
timeWindow: [MINUTE * 15, [Validators.required]],
|
||||||
});
|
});
|
||||||
|
|
||||||
argumentTypes: ArgumentType[];
|
argumentTypes: ArgumentType[];
|
||||||
@ -136,6 +140,12 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit {
|
|||||||
.filter(type => type !== ArgumentType.Rolling || this.calculatedFieldType === CalculatedFieldType.SCRIPT);
|
.filter(type => type !== ArgumentType.Rolling || this.calculatedFieldType === CalculatedFieldType.SCRIPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
if (this.entityHasError) {
|
||||||
|
this.entityAutocomplete.selectEntityFormGroup.get('entity').markAsTouched();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
saveArgument(): void {
|
saveArgument(): void {
|
||||||
const { refEntityId, ...restConfig } = this.argumentFormGroup.value;
|
const { refEntityId, ...restConfig } = this.argumentFormGroup.value;
|
||||||
const value = (refEntityId.entityType === ArgumentEntityType.Current ? restConfig : { refEntityId, ...restConfig }) as CalculatedFieldArgumentValue;
|
const value = (refEntityId.entityType === ArgumentEntityType.Current ? restConfig : { refEntityId, ...restConfig }) as CalculatedFieldArgumentValue;
|
||||||
|
|||||||
@ -89,7 +89,8 @@ export class EntityVersionCreateComponent extends PageComponent implements OnIni
|
|||||||
{entityName: this.entityName}), [Validators.required, Validators.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],
|
{entityName: this.entityName}), [Validators.required, Validators.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],
|
||||||
saveRelations: [false, []],
|
saveRelations: [false, []],
|
||||||
saveAttributes: [true, []],
|
saveAttributes: [true, []],
|
||||||
saveCredentials: [true, []]
|
saveCredentials: [true, []],
|
||||||
|
saveCalculatedFields: [true, []]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -187,18 +187,8 @@ export class ImportExportService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public importCalculatedField(entityId: EntityId): Observable<CalculatedField> {
|
public openCalculatedFieldImportDialog(): Observable<CalculatedField> {
|
||||||
return this.openImportDialog('calculated-fields.import', 'calculated-fields.file').pipe(
|
return this.openImportDialog('calculated-fields.import', 'calculated-fields.file').pipe(
|
||||||
mergeMap((calculatedField: CalculatedField) => {
|
|
||||||
if (!this.validateImportedCalculatedField({ entityId, ...calculatedField })) {
|
|
||||||
this.store.dispatch(new ActionNotificationShow(
|
|
||||||
{message: this.translate.instant('calculated-fields.invalid-file-error'),
|
|
||||||
type: 'error'}));
|
|
||||||
throw new Error('Invalid calculated field file');
|
|
||||||
} else {
|
|
||||||
return this.calculatedFieldsService.saveCalculatedField(this.prepareImport({ entityId, ...calculatedField }));
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
catchError(() => of(null)),
|
catchError(() => of(null)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -989,16 +979,6 @@ export class ImportExportService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private validateImportedCalculatedField(calculatedField: CalculatedField): boolean {
|
|
||||||
const { name, configuration, entityId } = calculatedField;
|
|
||||||
return isNotEmptyStr(name)
|
|
||||||
&& isDefined(configuration)
|
|
||||||
&& isDefined(entityId?.id)
|
|
||||||
&& !!Object.keys(configuration.arguments).length
|
|
||||||
&& isDefined(configuration.expression)
|
|
||||||
&& isDefined(configuration.output)
|
|
||||||
}
|
|
||||||
|
|
||||||
private validateImportedImage(image: ImageExportData): boolean {
|
private validateImportedImage(image: ImageExportData): boolean {
|
||||||
return !(!isNotEmptyStr(image.data)
|
return !(!isNotEmptyStr(image.data)
|
||||||
|| !isNotEmptyStr(image.title)
|
|| !isNotEmptyStr(image.title)
|
||||||
|
|||||||
@ -127,7 +127,7 @@ export const ArgumentTypeTranslations = new Map<ArgumentType, string>(
|
|||||||
export interface CalculatedFieldArgument {
|
export interface CalculatedFieldArgument {
|
||||||
refEntityKey: RefEntityKey;
|
refEntityKey: RefEntityKey;
|
||||||
defaultValue?: string;
|
defaultValue?: string;
|
||||||
refEntityId?: RefEntityKey;
|
refEntityId?: RefEntityId;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
timeWindow?: number;
|
timeWindow?: number;
|
||||||
}
|
}
|
||||||
@ -138,7 +138,7 @@ export interface RefEntityKey {
|
|||||||
scope?: AttributeScope;
|
scope?: AttributeScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RefEntityKey {
|
export interface RefEntityId {
|
||||||
entityType: ArgumentEntityType;
|
entityType: ArgumentEntityType;
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
@ -563,12 +563,12 @@ export const getCalculatedFieldArgumentsHighlights = (
|
|||||||
regex: `\\b${key}\\b`,
|
regex: `\\b${key}\\b`,
|
||||||
next: argumentsObj[key].refEntityKey.type === ArgumentType.Rolling
|
next: argumentsObj[key].refEntityKey.type === ArgumentType.Rolling
|
||||||
? 'calculatedFieldRollingArgumentValue'
|
? 'calculatedFieldRollingArgumentValue'
|
||||||
: 'start'
|
: 'no_regex'
|
||||||
}));
|
}));
|
||||||
const calculatedFieldCtxArgumentsHighlightRules = {
|
const calculatedFieldCtxArgumentsHighlightRules = {
|
||||||
calculatedFieldCtxArgs: [
|
calculatedFieldCtxArgs: [
|
||||||
dotOperatorHighlightRule,
|
dotOperatorHighlightRule,
|
||||||
...calculatedFieldArgumentsKeys.map(argumentRule => argumentRule.next === 'start' ? {...argumentRule, next: 'calculatedFieldSingleArgumentValue' } : argumentRule),
|
...calculatedFieldArgumentsKeys.map(argumentRule => argumentRule.next === 'no_regex' ? {...argumentRule, next: 'calculatedFieldSingleArgumentValue' } : argumentRule),
|
||||||
endGroupHighlightRule
|
endGroupHighlightRule
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1074,7 +1074,8 @@
|
|||||||
"argument-type-required": "Argument type is required.",
|
"argument-type-required": "Argument type is required.",
|
||||||
"max-args": "Maximum number of arguments reached.",
|
"max-args": "Maximum number of arguments reached.",
|
||||||
"decimals-range": "Decimals by default should be a number between 0 and 15.",
|
"decimals-range": "Decimals by default should be a number between 0 and 15.",
|
||||||
"expression": "Default expression demonstrates how to transform a temperature from Fahrenheit to Celsius."
|
"expression": "Default expression demonstrates how to transform a temperature from Fahrenheit to Celsius.",
|
||||||
|
"arguments-entity-not-found": "Argument target entity not found."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"confirm-on-exit": {
|
"confirm-on-exit": {
|
||||||
@ -5570,12 +5571,12 @@
|
|||||||
"max-calculated-fields": "Calculated fields per entity maximum number",
|
"max-calculated-fields": "Calculated fields per entity maximum number",
|
||||||
"max-calculated-fields-range": "Calculated fields per entity maximum number can't be negative",
|
"max-calculated-fields-range": "Calculated fields per entity maximum number can't be negative",
|
||||||
"max-calculated-fields-required": "Calculated fields per entity maximum number is required",
|
"max-calculated-fields-required": "Calculated fields per entity maximum number is required",
|
||||||
"max-data-points-per-rolling-arg": "Maximum data points number in rolling arguments",
|
"max-data-points-per-rolling-arg": "Max data points number in rolling arguments",
|
||||||
"max-data-points-per-rolling-arg-range": "Maximum data points number in rolling arguments can't be negative",
|
"max-data-points-per-rolling-arg-range": "Max data points number in rolling arguments can't be negative",
|
||||||
"max-data-points-per-rolling-arg-required": "Maximum data points number in rolling arguments is required",
|
"max-data-points-per-rolling-arg-required": "Max data points number in rolling arguments is required",
|
||||||
"max-arguments-per-cf": "Arguments per calculated field maximum number",
|
"max-arguments-per-cf": "Arguments per calculated field max number",
|
||||||
"max-arguments-per-cf-range": "Arguments per calculated field maximum number can't be negative",
|
"max-arguments-per-cf-range": "Arguments per calculated field max number can't be negative",
|
||||||
"max-arguments-per-cf-required": "Arguments per calculated field maximum number is required",
|
"max-arguments-per-cf-required": "Arguments per calculated field max number is required",
|
||||||
"max-state-size": "State maximum size in KB",
|
"max-state-size": "State maximum size in KB",
|
||||||
"max-state-size-range": "State maximum size in KB can't be negative",
|
"max-state-size-range": "State maximum size in KB can't be negative",
|
||||||
"max-state-size-required": "State maximum size in KB is required",
|
"max-state-size-required": "State maximum size in KB is required",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user