NIFI-14031: Ensuring all Parameter Contexts are added when Editing a … (#9539)

* NIFI-14031: Ensuring all Parameter Contexts are added when Editing a Process Group. For contexts the user lacks access to will be added as disabled options.

* NIFI-14031: Addressing review feedback allowing the currently selected value to be reselected even when the user lacks permissions because the back end skips the check when the value isn't changing.

* NIFI-14031: Fixing PropertyItem instances in unit tests.

This closes #9539
This commit is contained in:
Matt Gilman 2024-11-20 17:13:31 -05:00 committed by GitHub
parent 685f5712b7
commit b421ccad21
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 37 additions and 19 deletions

View File

@ -37,7 +37,7 @@
@if (option.description) {
<mat-option
[value]="option.value"
[disabled]="readonly"
[disabled]="readonly || option.disabled"
nifiTooltip
[tooltipComponentType]="TextTip"
[tooltipInputData]="option.description"
@ -45,9 +45,11 @@
>{{ option.text }}</mat-option
>
} @else {
<mat-option [value]="option.value" [disabled]="readonly">{{
option.text
}}</mat-option>
<mat-option
[value]="option.value"
[disabled]="readonly || option.disabled"
>{{ option.text }}</mat-option
>
}
}
</mat-select>

View File

@ -31,10 +31,8 @@ import { ParameterContextEntity } from '../../../../../../../state/shared';
import { Client } from '../../../../../../../service/client.service';
import { NifiSpinnerDirective } from '../../../../../../../ui/common/spinner/nifi-spinner.directive';
import { NifiTooltipDirective, TextTip } from '@nifi/shared';
import { ControllerServiceTable } from '../../../../../../../ui/common/controller-service/controller-service-table/controller-service-table.component';
import { EditComponentDialogRequest } from '../../../../../state/flow';
import { ClusterConnectionService } from '../../../../../../../service/cluster-connection.service';
import { ErrorBanner } from '../../../../../../../ui/common/error-banner/error-banner.component';
import { TabbedDialog } from '../../../../../../../ui/common/tabbed-dialog/tabbed-dialog.component';
import { ErrorContextKey } from '../../../../../../../state/error';
import { ContextErrorBanner } from '../../../../../../../ui/common/context-error-banner/context-error-banner.component';
@ -56,8 +54,6 @@ import { ContextErrorBanner } from '../../../../../../../ui/common/context-error
NifiSpinnerDirective,
NifiTooltipDirective,
FormsModule,
ControllerServiceTable,
ErrorBanner,
ContextErrorBanner
],
styleUrls: ['./edit-process-group.component.scss']
@ -71,6 +67,12 @@ export class EditProcessGroup extends TabbedDialog {
value: parameterContext.id,
description: parameterContext.component.description
});
} else {
this.parameterContextsOptions.push({
text: parameterContext.id,
value: parameterContext.id,
disabled: this.request.entity.component.parameterContext.id !== parameterContext.id
});
}
});

View File

@ -31,7 +31,7 @@
<ng-container *ngIf="allowableValue.description; else noDescription">
<mat-option
[value]="allowableValue.id"
[disabled]="readonly"
[disabled]="readonly || allowableValue.disabled"
(mousedown)="preventDrag($event)"
nifiTooltip
[tooltipComponentType]="TextTip"
@ -48,7 +48,7 @@
<ng-template #noDescription>
<mat-option
[value]="allowableValue.id"
[disabled]="readonly"
[disabled]="readonly || allowableValue.disabled"
(mousedown)="preventDrag($event)">
<span
class="option-text"

View File

@ -115,6 +115,7 @@ describe('ComboEditor', () => {
deleted: false,
added: false,
dirty: false,
savedValue: 'flowfile-attribute',
type: 'required'
};
});

View File

@ -17,13 +17,13 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { PropertyItem } from '../../property-table.component';
import { CdkDrag, CdkDragHandle } from '@angular/cdk/drag-drop';
import { CdkDrag } from '@angular/cdk/drag-drop';
import { AbstractControl, FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatDialogModule } from '@angular/material/dialog';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { NgForOf, NgIf, NgTemplateOutlet } from '@angular/common';
import { NgForOf, NgIf } from '@angular/common';
import { AllowableValue, Parameter, ParameterConfig, PropertyDescriptor } from '../../../../../state/shared';
import { MatOptionModule } from '@angular/material/core';
import { MatSelectModule } from '@angular/material/select';
@ -33,6 +33,7 @@ import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
export interface AllowableValueItem extends AllowableValue {
id: number;
disabled: boolean;
}
@Component({
@ -41,13 +42,11 @@ export interface AllowableValueItem extends AllowableValue {
templateUrl: './combo-editor.component.html',
imports: [
CdkDrag,
CdkDragHandle,
ReactiveFormsModule,
MatDialogModule,
MatInputModule,
MatButtonModule,
MatCheckboxModule,
NgTemplateOutlet,
NifiTooltipDirective,
MatOptionModule,
MatSelectModule,
@ -68,6 +67,7 @@ export class ComboEditor {
this.descriptor = item.descriptor;
this.sensitive = item.descriptor.sensitive;
this.savedValue = item.savedValue;
this.itemSet = true;
this.initialAllowableValues();
@ -102,6 +102,7 @@ export class ComboEditor {
itemSet = false;
configuredValue: string | null = null;
savedValue: string | null = null;
parameters: Parameter[] | null = null;
constructor(
@ -125,6 +126,7 @@ export class ComboEditor {
if (!this.descriptor.required) {
const noValue: AllowableValueItem = {
id: i++,
disabled: false,
displayName: 'No value',
value: null
};
@ -141,7 +143,10 @@ export class ComboEditor {
(allowableValueEntity) => {
const allowableValue: AllowableValueItem = {
...allowableValueEntity.allowableValue,
id: i++
id: i++,
disabled:
!allowableValueEntity.canRead &&
allowableValueEntity.allowableValue.value !== this.savedValue
};
this.itemLookup.set(allowableValue.id, allowableValue);
@ -160,6 +165,7 @@ export class ComboEditor {
// and hiding the parameter options select
const referencesParameterOption: AllowableValueItem = {
id: i++,
disabled: false,
displayName: 'Reference Parameter...',
value: null
};
@ -187,6 +193,7 @@ export class ComboEditor {
this.parameters.forEach((parameter) => {
const parameterItem: AllowableValueItem = {
id: i++,
disabled: false,
displayName: parameter.name,
value: `#{${parameter.name}}`,
description: parameter.description

View File

@ -62,6 +62,7 @@ describe('NfEditor', () => {
deleted: false,
added: false,
dirty: false,
savedValue: value,
type: 'required'
};
@ -99,6 +100,7 @@ describe('NfEditor', () => {
deleted: false,
added: false,
dirty: false,
savedValue: value,
type: 'required'
};

View File

@ -31,7 +31,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { NiFiCommon, NifiTooltipDirective, TextTip } from '@nifi/shared';
import { AsyncPipe, NgTemplateOutlet } from '@angular/common';
import { NgTemplateOutlet } from '@angular/common';
import {
AllowableValueEntity,
ComponentHistory,
@ -57,7 +57,6 @@ import {
import { ComboEditor } from './editors/combo-editor/combo-editor.component';
import { Observable, take } from 'rxjs';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { RouterLink } from '@angular/router';
import { ConvertToParameterResponse } from '../../../pages/flow-designer/service/parameter-helper.service';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
@ -68,6 +67,7 @@ export interface PropertyItem extends Property {
dirty: boolean;
added: boolean;
type: 'required' | 'userDefined' | 'optional';
savedValue: string | null;
serviceLink?: string[];
}
@ -85,8 +85,6 @@ export interface PropertyItem extends Property {
CdkOverlayOrigin,
CdkConnectedOverlay,
ComboEditor,
RouterLink,
AsyncPipe,
MatMenu,
MatMenuItem,
MatMenuTrigger
@ -299,6 +297,7 @@ export class PropertyTable implements AfterViewInit, ControlValueAccessor {
deleted: false,
added: false,
dirty: false,
savedValue: property.value,
type: property.descriptor.required
? 'required'
: property.descriptor.dynamic
@ -383,6 +382,7 @@ export class PropertyTable implements AfterViewInit, ControlValueAccessor {
deleted: false,
added: true,
dirty: true,
savedValue: property.value,
type: property.descriptor.required
? 'required'
: property.descriptor.dynamic
@ -571,6 +571,10 @@ export class PropertyTable implements AfterViewInit, ControlValueAccessor {
savePropertyValue(item: PropertyItem, newValue: string | null): void {
if (item.value != newValue) {
if (!item.savedValue) {
item.savedValue = item.value;
}
item.value = newValue;
item.dirty = true;