mirror of https://github.com/apache/nifi.git
NIFI-13299: (#8894)
- Adding min validators where appropriate. This closes #8894
This commit is contained in:
parent
89e8434bf0
commit
2cd4624825
|
@ -100,20 +100,45 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>FlowFile Expiration</mat-label>
|
<mat-label>
|
||||||
|
FlowFile Expiration
|
||||||
|
<i
|
||||||
|
class="fa fa-info-circle"
|
||||||
|
nifiTooltip
|
||||||
|
[tooltipComponentType]="TextTip"
|
||||||
|
tooltipInputData="The maximum amount of time an object may be in the flow before it will be automatically aged out of the flow."></i>
|
||||||
|
</mat-label>
|
||||||
<input matInput formControlName="flowFileExpiration" type="text" />
|
<input matInput formControlName="flowFileExpiration" type="text" />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-x-2">
|
<div class="flex gap-x-2">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>Back Pressure Object Threshold</mat-label>
|
<mat-label>
|
||||||
<input matInput formControlName="backPressureObjectThreshold" type="number" />
|
Back Pressure Object Threshold
|
||||||
|
<i
|
||||||
|
class="fa fa-info-circle"
|
||||||
|
nifiTooltip
|
||||||
|
[tooltipComponentType]="TextTip"
|
||||||
|
tooltipInputData="The maximum number of objects that can be queued before back pressure is applied. Must be a non-negative integer."></i>
|
||||||
|
</mat-label>
|
||||||
|
<input
|
||||||
|
matInput
|
||||||
|
formControlName="backPressureObjectThreshold"
|
||||||
|
type="number"
|
||||||
|
min="0" />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>Size Threshold</mat-label>
|
<mat-label>
|
||||||
|
Size Threshold
|
||||||
|
<i
|
||||||
|
class="fa fa-info-circle"
|
||||||
|
nifiTooltip
|
||||||
|
[tooltipComponentType]="TextTip"
|
||||||
|
tooltipInputData="The maximum data size of objects that can be queued before back pressure is applied."></i>
|
||||||
|
</mat-label>
|
||||||
<input matInput formControlName="backPressureDataSizeThreshold" type="text" />
|
<input matInput formControlName="backPressureDataSizeThreshold" type="text" />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
@ -121,7 +146,14 @@
|
||||||
<div class="flex gap-x-2">
|
<div class="flex gap-x-2">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>Load Balance Strategy</mat-label>
|
<mat-label>
|
||||||
|
Load Balance Strategy
|
||||||
|
<i
|
||||||
|
class="fa fa-info-circle"
|
||||||
|
nifiTooltip
|
||||||
|
[tooltipComponentType]="TextTip"
|
||||||
|
tooltipInputData="How to load balance the data in this Connection across the nodes in the cluster."></i>
|
||||||
|
</mat-label>
|
||||||
<mat-select
|
<mat-select
|
||||||
formControlName="loadBalanceStrategy"
|
formControlName="loadBalanceStrategy"
|
||||||
(selectionChange)="loadBalanceChanged($event.value)">
|
(selectionChange)="loadBalanceChanged($event.value)">
|
||||||
|
@ -141,7 +173,14 @@
|
||||||
@if (loadBalancePartitionAttributeRequired) {
|
@if (loadBalancePartitionAttributeRequired) {
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>Attribute Name</mat-label>
|
<mat-label>
|
||||||
|
Attribute Name
|
||||||
|
<i
|
||||||
|
class="fa fa-info-circle"
|
||||||
|
nifiTooltip
|
||||||
|
[tooltipComponentType]="TextTip"
|
||||||
|
tooltipInputData="The FlowFile Attribute to use for determining which node a FlowFile will go to."></i>
|
||||||
|
</mat-label>
|
||||||
<input matInput formControlName="partitionAttribute" type="text" />
|
<input matInput formControlName="partitionAttribute" type="text" />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
@ -150,7 +189,14 @@
|
||||||
@if (loadBalanceCompressionRequired) {
|
@if (loadBalanceCompressionRequired) {
|
||||||
<div>
|
<div>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>Load Balance Compression</mat-label>
|
<mat-label>
|
||||||
|
Load Balance Compression
|
||||||
|
<i
|
||||||
|
class="fa fa-info-circle"
|
||||||
|
nifiTooltip
|
||||||
|
[tooltipComponentType]="TextTip"
|
||||||
|
tooltipInputData="Whether or not data should be compressed when being transferred between nodes in the cluster."></i>
|
||||||
|
</mat-label>
|
||||||
<mat-select formControlName="compression">
|
<mat-select formControlName="compression">
|
||||||
@for (option of loadBalanceCompressionStrategies; track option) {
|
@for (option of loadBalanceCompressionStrategies; track option) {
|
||||||
<mat-option
|
<mat-option
|
||||||
|
|
|
@ -152,7 +152,10 @@ export class CreateConnection extends CloseOnEscapeDialog {
|
||||||
this.createConnectionForm = this.formBuilder.group({
|
this.createConnectionForm = this.formBuilder.group({
|
||||||
name: new FormControl(''),
|
name: new FormControl(''),
|
||||||
flowFileExpiration: new FormControl(dialogRequest.defaults.flowfileExpiration, Validators.required),
|
flowFileExpiration: new FormControl(dialogRequest.defaults.flowfileExpiration, Validators.required),
|
||||||
backPressureObjectThreshold: new FormControl(dialogRequest.defaults.objectThreshold, Validators.required),
|
backPressureObjectThreshold: new FormControl(dialogRequest.defaults.objectThreshold, [
|
||||||
|
Validators.required,
|
||||||
|
Validators.min(0)
|
||||||
|
]),
|
||||||
backPressureDataSizeThreshold: new FormControl(
|
backPressureDataSizeThreshold: new FormControl(
|
||||||
dialogRequest.defaults.dataSizeThreshold,
|
dialogRequest.defaults.dataSizeThreshold,
|
||||||
Validators.required
|
Validators.required
|
||||||
|
|
|
@ -135,12 +135,13 @@
|
||||||
class="fa fa-info-circle"
|
class="fa fa-info-circle"
|
||||||
nifiTooltip
|
nifiTooltip
|
||||||
[tooltipComponentType]="TextTip"
|
[tooltipComponentType]="TextTip"
|
||||||
tooltipInputData="The maximum number of objects that can be queued before back pressure is applied."></i>
|
tooltipInputData="The maximum number of objects that can be queued before back pressure is applied. Must be a non-negative integer."></i>
|
||||||
</mat-label>
|
</mat-label>
|
||||||
<input
|
<input
|
||||||
matInput
|
matInput
|
||||||
formControlName="backPressureObjectThreshold"
|
formControlName="backPressureObjectThreshold"
|
||||||
type="number"
|
type="number"
|
||||||
|
min="0"
|
||||||
[readonly]="connectionReadonly || sourceReadonly || destinationReadonly" />
|
[readonly]="connectionReadonly || sourceReadonly || destinationReadonly" />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -264,7 +264,10 @@ export class EditConnectionComponent extends TabbedDialog {
|
||||||
this.editConnectionForm = this.formBuilder.group({
|
this.editConnectionForm = this.formBuilder.group({
|
||||||
name: new FormControl(connection.name),
|
name: new FormControl(connection.name),
|
||||||
flowFileExpiration: new FormControl(connection.flowFileExpiration, Validators.required),
|
flowFileExpiration: new FormControl(connection.flowFileExpiration, Validators.required),
|
||||||
backPressureObjectThreshold: new FormControl(connection.backPressureObjectThreshold, Validators.required),
|
backPressureObjectThreshold: new FormControl(connection.backPressureObjectThreshold, [
|
||||||
|
Validators.required,
|
||||||
|
Validators.min(0)
|
||||||
|
]),
|
||||||
backPressureDataSizeThreshold: new FormControl(
|
backPressureDataSizeThreshold: new FormControl(
|
||||||
connection.backPressureDataSizeThreshold,
|
connection.backPressureDataSizeThreshold,
|
||||||
Validators.required
|
Validators.required
|
||||||
|
|
|
@ -151,7 +151,7 @@
|
||||||
class="fa fa-info-circle"
|
class="fa fa-info-circle"
|
||||||
nifiTooltip
|
nifiTooltip
|
||||||
[tooltipComponentType]="TextTip"
|
[tooltipComponentType]="TextTip"
|
||||||
tooltipInputData="The number of tasks that should be concurrently scheduled for this processor."></i>
|
tooltipInputData="The number of tasks that should be concurrently scheduled for this processor. Must be an integer greater than 0."></i>
|
||||||
</mat-label>
|
</mat-label>
|
||||||
<input
|
<input
|
||||||
matInput
|
matInput
|
||||||
|
@ -159,6 +159,7 @@
|
||||||
(change)="concurrentTasksChanged()"
|
(change)="concurrentTasksChanged()"
|
||||||
name="concurrentTasks"
|
name="concurrentTasks"
|
||||||
type="number"
|
type="number"
|
||||||
|
min="1"
|
||||||
[readonly]="readonly" />
|
[readonly]="readonly" />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -17,7 +17,16 @@
|
||||||
|
|
||||||
import { Component, EventEmitter, Inject, Input, Output } from '@angular/core';
|
import { Component, EventEmitter, Inject, Input, Output } from '@angular/core';
|
||||||
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
||||||
import { AbstractControl, FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
import {
|
||||||
|
AbstractControl,
|
||||||
|
FormBuilder,
|
||||||
|
FormControl,
|
||||||
|
FormGroup,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
ValidationErrors,
|
||||||
|
ValidatorFn,
|
||||||
|
Validators
|
||||||
|
} from '@angular/forms';
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input';
|
||||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
@ -226,14 +235,14 @@ export class EditProcessor extends TabbedDialog {
|
||||||
yieldDuration: new FormControl(request.entity.component.config.yieldDuration, Validators.required),
|
yieldDuration: new FormControl(request.entity.component.config.yieldDuration, Validators.required),
|
||||||
bulletinLevel: new FormControl(request.entity.component.config.bulletinLevel, Validators.required),
|
bulletinLevel: new FormControl(request.entity.component.config.bulletinLevel, Validators.required),
|
||||||
schedulingStrategy: new FormControl(this.schedulingStrategy, Validators.required),
|
schedulingStrategy: new FormControl(this.schedulingStrategy, Validators.required),
|
||||||
concurrentTasks: new FormControl(concurrentTasks, Validators.required),
|
concurrentTasks: new FormControl(concurrentTasks, [Validators.required, Validators.min(1)]),
|
||||||
schedulingPeriod: new FormControl(schedulingPeriod, Validators.required),
|
schedulingPeriod: new FormControl(schedulingPeriod, Validators.required),
|
||||||
executionNode: new FormControl(request.entity.component.config.executionNode, Validators.required),
|
executionNode: new FormControl(request.entity.component.config.executionNode, Validators.required),
|
||||||
properties: new FormControl({ value: properties, disabled: this.readonly }),
|
properties: new FormControl({ value: properties, disabled: this.readonly }),
|
||||||
relationshipConfiguration: new FormControl(
|
relationshipConfiguration: new FormControl({ value: relationshipConfiguration, disabled: this.readonly }, [
|
||||||
{ value: relationshipConfiguration, disabled: this.readonly },
|
Validators.required,
|
||||||
Validators.required
|
this.relationshipConfigurationValidator()
|
||||||
),
|
]),
|
||||||
comments: new FormControl(request.entity.component.config.comments)
|
comments: new FormControl(request.entity.component.config.comments)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -245,6 +254,35 @@ export class EditProcessor extends TabbedDialog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private relationshipConfigurationValidator(): ValidatorFn {
|
||||||
|
return (control: AbstractControl): ValidationErrors | null => {
|
||||||
|
const relationshipConfiguration: RelationshipConfiguration = control.value;
|
||||||
|
const retried: string[] = relationshipConfiguration.relationships
|
||||||
|
.filter((relationship) => relationship.retry)
|
||||||
|
.map((relationship) => relationship.name);
|
||||||
|
|
||||||
|
if (retried.length > 0) {
|
||||||
|
let hasErrors = false;
|
||||||
|
const errors: ValidationErrors = {};
|
||||||
|
|
||||||
|
if (relationshipConfiguration.retryCount == null || relationshipConfiguration.retryCount < 0) {
|
||||||
|
errors['invalidRetry'] = true;
|
||||||
|
hasErrors = true;
|
||||||
|
}
|
||||||
|
if (this.nifiCommon.isBlank(relationshipConfiguration.maxBackoffPeriod)) {
|
||||||
|
errors['invalidBackoff'] = true;
|
||||||
|
hasErrors = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasErrors) {
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
supportsBatching(): boolean {
|
supportsBatching(): boolean {
|
||||||
return this.request.entity.component.supportsBatching == true;
|
return this.request.entity.component.supportsBatching == true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,14 +71,16 @@
|
||||||
class="fa fa-info-circle"
|
class="fa fa-info-circle"
|
||||||
nifiTooltip
|
nifiTooltip
|
||||||
[tooltipComponentType]="TextTip"
|
[tooltipComponentType]="TextTip"
|
||||||
tooltipInputData="For relationships set to retry, this number indicates how many times a FlowFile will attempt to reprocess before it is routed elsewhere."></i>
|
tooltipInputData="For relationships set to retry, this number indicates how many times a FlowFile will attempt to reprocess before it is routed elsewhere. Must be a non-negative integer."></i>
|
||||||
</mat-label>
|
</mat-label>
|
||||||
<input
|
<input
|
||||||
matInput
|
matInput
|
||||||
[(ngModel)]="retryCount"
|
[(ngModel)]="retryCount"
|
||||||
type="number"
|
type="number"
|
||||||
|
min="0"
|
||||||
name="retryCount"
|
name="retryCount"
|
||||||
(keyup)="handleChanged()"
|
(keyup)="handleChanged()"
|
||||||
|
[required]="true"
|
||||||
[readonly]="isDisabled" />
|
[readonly]="isDisabled" />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
@ -115,6 +117,7 @@
|
||||||
[(ngModel)]="maxBackoffPeriod"
|
[(ngModel)]="maxBackoffPeriod"
|
||||||
type="text"
|
type="text"
|
||||||
(keyup)="handleChanged()"
|
(keyup)="handleChanged()"
|
||||||
|
[required]="true"
|
||||||
[readonly]="isDisabled" />
|
[readonly]="isDisabled" />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue