) {
this.entityAggregationConfiguration.get('interval.type').valueChanges.pipe(
takeUntilDestroyed()
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html
index 8cfa8fd0ed..2c2f7b5973 100644
--- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html
+++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html
@@ -342,17 +342,17 @@
- tenant-profile.relation-search-entity-limit
- tenant-profile.min-allowed-aggregation-interval
+
-
- {{ 'tenant-profile.relation-search-entity-limit-required' | translate}}
+
+ {{ 'tenant-profile.min-allowed-aggregation-interval-required' | translate}}
-
- {{ 'tenant-profile.relation-search-entity-limit-range' | translate}}
+
+ {{ 'tenant-profile.min-allowed-aggregation-interval-range' | translate}}
- tenant-profile.relation-search-entity-limit-hint
+
tenant-profile.min-allowed-deduplication-interval
@@ -368,6 +368,22 @@
+
+
+ tenant-profile.relation-search-entity-limit
+
+
+ {{ 'tenant-profile.relation-search-entity-limit-required' | translate}}
+
+
+ {{ 'tenant-profile.relation-search-entity-limit-range' | translate}}
+
+ tenant-profile.relation-search-entity-limit-hint
+
+
+
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts
index 0000d01995..16997d18a7 100644
--- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts
+++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts
@@ -117,6 +117,7 @@ export class DefaultTenantProfileConfigurationComponent implements ControlValueA
maxArgumentsPerCF: [0, [Validators.required, Validators.min(0)]],
maxRelationLevelPerCfArgument: [1, [Validators.required, Validators.min(1)]],
minAllowedDeduplicationIntervalInSecForCF: [0, [Validators.required, Validators.min(0)]],
+ minAggregationIntervalInSecForCF: [0, [Validators.required, Validators.min(0)]],
maxRelatedEntitiesToReturnPerCfArgument: [1, [Validators.required, Validators.min(1)]],
minAllowedScheduledUpdateIntervalInSecForCF: [0, [Validators.required, Validators.min(0)]],
maxDataPointsPerRollingArg: [0, [Validators.required, Validators.min(0)]],
diff --git a/ui-ngx/src/app/shared/components/time-unit-input.component.html b/ui-ngx/src/app/shared/components/time-unit-input.component.html
index f81fc68777..c49ce517b3 100644
--- a/ui-ngx/src/app/shared/components/time-unit-input.component.html
+++ b/ui-ngx/src/app/shared/components/time-unit-input.component.html
@@ -15,7 +15,7 @@
limitations under the License.
-->
-
+
diff --git a/ui-ngx/src/app/shared/components/time-unit-input.component.ts b/ui-ngx/src/app/shared/components/time-unit-input.component.ts
index bcfdabd574..65acaa88f1 100644
--- a/ui-ngx/src/app/shared/components/time-unit-input.component.ts
+++ b/ui-ngx/src/app/shared/components/time-unit-input.component.ts
@@ -23,6 +23,7 @@ import {
NG_VALUE_ACCESSOR,
ValidationErrors,
Validator,
+ ValidatorFn,
Validators
} from '@angular/forms';
import { TimeUnit, timeUnitTranslations } from '@home/components/rule-node/rule-node-config.models';
@@ -79,6 +80,13 @@ export class TimeUnitInputComponent implements ControlValueAccessor, Validator,
@Input()
maxErrorText: string;
+ @Input()
+ @coerceNumber()
+ stepMultipleOf: number;
+
+ @Input()
+ stepMultipleOfErrorText: string;
+
@Input()
subscriptSizing: SubscriptSizing = 'fixed';
@@ -93,6 +101,9 @@ export class TimeUnitInputComponent implements ControlValueAccessor, Validator,
@coerceBoolean()
sameWidthInputs: boolean = false;
+ @Input()
+ containerClass: string | string[] | Record = "flex gap-4";
+
timeUnits = Object.values(TimeUnit).filter(item => item !== TimeUnit.MILLISECONDS) as TimeUnit[];
timeUnitTranslations = timeUnitTranslations;
@@ -128,7 +139,7 @@ export class TimeUnitInputComponent implements ControlValueAccessor, Validator,
this.timeUnits = this.timeUnits.filter(item => item !== TimeUnit.DAYS);
}
}
- if(this.required || this.maxTime) {
+ if (this.required || this.maxTime || isDefinedAndNotNull(this.minTime) || this.stepMultipleOf) {
const timeControl = this.timeInputForm.get('time');
const validators = [Validators.pattern(/^\d*$/)];
if (this.required) {
@@ -145,6 +156,10 @@ export class TimeUnitInputComponent implements ControlValueAccessor, Validator,
);
}
+ if (isDefinedAndNotNull(this.stepMultipleOf) && this.stepMultipleOf > 0) {
+ validators.push(this.createStepMultipleOfValidator());
+ }
+
timeControl.setValidators(validators);
timeControl.updateValueAndValidity({ emitEvent: false });
}
@@ -170,6 +185,8 @@ export class TimeUnitInputComponent implements ControlValueAccessor, Validator,
return this.minErrorText;
} else if (this.timeInputForm.get('time').hasError('max') && this.maxErrorText) {
return this.maxErrorText;
+ } else if (this.timeInputForm.get('time').hasError('stepMultipleOf') && this.stepMultipleOfErrorText) {
+ return this.stepMultipleOfErrorText;
}
}
@@ -232,4 +249,34 @@ export class TimeUnitInputComponent implements ControlValueAccessor, Validator,
}
}
+ private createStepMultipleOfValidator(): ValidatorFn {
+ return (control: AbstractControl): ValidationErrors | null => {
+ const time = control.value;
+ if (!isDefinedAndNotNull(time) || !isNumeric(time)) {
+ return null;
+ }
+ const numericTime = Number(time);
+ if (numericTime === 0) {
+ return null;
+ }
+
+ const timeUnit = control.parent?.get('timeUnit')?.value as TimeUnit;
+ if (!timeUnit) {
+ return null;
+ }
+
+ const unitInSec = this.timeIntervalsInSec.get(timeUnit);
+ const totalTimeInSec = numericTime * unitInSec;
+ const multipleOfVal = this.stepMultipleOf;
+
+ let isValid: boolean;
+ if (totalTimeInSec < multipleOfVal) {
+ isValid = (multipleOfVal % totalTimeInSec === 0);
+ } else {
+ isValid = (totalTimeInSec % multipleOfVal === 0);
+ }
+ return isValid ? null : { stepMultipleOf: true };
+ };
+ }
+
}
diff --git a/ui-ngx/src/app/shared/models/calculated-field.models.ts b/ui-ngx/src/app/shared/models/calculated-field.models.ts
index 321c176cde..e0df001e3f 100644
--- a/ui-ngx/src/app/shared/models/calculated-field.models.ts
+++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts
@@ -135,8 +135,7 @@ export interface CalculatedFieldEntityAggregationConfiguration {
}
export interface WatermarkConfig {
- duration?: number;
- checkInterval?: number;
+ duration: number;
}
interface BasePropagationConfiguration {
diff --git a/ui-ngx/src/app/shared/models/tenant.model.ts b/ui-ngx/src/app/shared/models/tenant.model.ts
index ae7a0ae8b8..ac7b77b9cc 100644
--- a/ui-ngx/src/app/shared/models/tenant.model.ts
+++ b/ui-ngx/src/app/shared/models/tenant.model.ts
@@ -108,6 +108,7 @@ export interface DefaultTenantProfileConfiguration {
maxArgumentsPerCF: number;
maxRelationLevelPerCfArgument: number;
minAllowedDeduplicationIntervalInSecForCF: number;
+ minAggregationIntervalInSecForCF: number;
maxRelatedEntitiesToReturnPerCfArgument: number;
minAllowedScheduledUpdateIntervalInSecForCF: number;
maxDataPointsPerRollingArg: number;
@@ -176,6 +177,7 @@ export function createTenantProfileConfiguration(type: TenantProfileType): Tenan
maxDataPointsPerRollingArg: 1000,
maxRelationLevelPerCfArgument: 10,
minAllowedDeduplicationIntervalInSecForCF: 3600,
+ minAggregationIntervalInSecForCF: 60,
maxRelatedEntitiesToReturnPerCfArgument: 100,
minAllowedScheduledUpdateIntervalInSecForCF: 0,
maxStateSizeInKBytes: 32,
diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json
index 6e00b883b4..c05686b648 100644
--- a/ui-ngx/src/assets/locale/locale.constant-en_US.json
+++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json
@@ -1195,7 +1195,8 @@
"aggregate-interval-type": "Aggregate interval type",
"aggregate-interval-value": "Aggregate interval value",
"aggregate-interval-value-required": "Aggregate interval value is required",
- "aggregate-interval-value-min": "Aggregate interval value should be at least 1 minute",
+ "aggregate-interval-value-min": "Aggregate interval value should be at least { sec, plural, =0 {0 second} =1 {1 second} other {# seconds} }",
+ "aggregate-interval-value-step-multiple-of": "Aggregate interval value must be a divisor or multiple of 1 day",
"aggregate-period": {
"hour": "Hour",
"day": "Day",
@@ -1220,12 +1221,7 @@
"duration": "Duration",
"duration-required": "Duration is required",
"duration-min": "Duration should be at least 1 minute",
- "duration-hint": "Defines how long to wait for delayed data after the interval ends",
- "check-interval": "Check for telemetry every",
- "check-interval-required": "Check for telemetry every is required",
- "check-interval-min": "Check interval should be at least 30 seconds",
- "check-interval-max": "Check interval need be less than the duration",
- "check-interval-hint": "Defines how often to recheck for late telemetry during the watermark period"
+ "duration-hint": "How long to wait for delayed data after the interval ends"
},
"hint": {
"arguments-simple-with-rolling": "Simple type calculated field should not contain keys with time series rolling type.",
@@ -6001,6 +5997,9 @@
"min-allowed-deduplication-interval": "Min allowed deduplication interval (seconds)",
"min-allowed-deduplication-interval-range": "Min allowed deduplication interval value can't be negative",
"min-allowed-deduplication-interval-required": "Min allowed deduplication interval is required",
+ "min-allowed-aggregation-interval": "Min allowed aggregation interval (seconds)",
+ "min-allowed-aggregation-interval-range": "Min allowed aggregation interval value can't be negative",
+ "min-allowed-aggregation-interval-required": "Min allowed aggregation interval is required",
"min-allowed-scheduled-update-interval-required": "Min allowed update interval min number is required",
"max-state-size": "State maximum size in KB",
"max-state-size-range": "State maximum size in KB can't be negative",