From 05575364a317d052e465bee4ad1ff66473172f3a Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Wed, 29 Nov 2023 17:21:35 -0500 Subject: [PATCH] NIFI-12417: Process Group Configuration (#8075) * NIFI-12417: - Process Group Configuration. - Removed unnecessary module imports. * NIFI-12417: - Addressing review feedback. This closes #8075 --- .../src/main/nifi/angular.json | 3 +- .../src/main/nifi/src/app/app.module.ts | 2 - .../canvas/service/canvas-utils.service.ts | 11 +- .../pages/canvas/state/flow/flow.actions.ts | 5 + .../pages/canvas/state/flow/flow.effects.ts | 84 ++++++- .../context-menu/context-menu.component.ts | 21 +- .../edit-process-group.component.html | 162 +++++++++++++ .../edit-process-group.component.scss | 36 +++ .../edit-process-group.component.spec.ts | 149 ++++++++++++ .../edit-process-group.component.ts | 227 ++++++++++++++++++ 10 files changed, 671 insertions(+), 29 deletions(-) create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.html create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.scss create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.spec.ts create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.ts diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/angular.json b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/angular.json index 0e74b49949..75fcedea38 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/angular.json +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/angular.json @@ -45,7 +45,8 @@ "vendorChunk": true, "extractLicenses": false, "sourceMap": true, - "namedChunks": true + "namedChunks": true, + "outputHashing": "none" } }, "defaultConfiguration": "production" diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/app.module.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/app.module.ts index d0a5adcf7b..cb45fb4c1a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/app.module.ts +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/app.module.ts @@ -44,8 +44,6 @@ import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field'; BrowserModule, AppRoutingModule, BrowserAnimationsModule, - FlowDesignerModule, - LoginModule, HttpClientModule, HttpClientXsrfModule.withOptions({ cookieName: '__Secure-Request-Token', diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/service/canvas-utils.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/service/canvas-utils.service.ts index 26109f74e1..a184c5ddf2 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/service/canvas-utils.service.ts +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/service/canvas-utils.service.ts @@ -307,14 +307,15 @@ export class CanvasUtils { * @param selection */ public isConfigurable(selection: any): boolean { - // ensure the correct number of components are selected - if (selection.size() !== 1) { - return selection.empty(); + if (selection.empty()) { + return this.canvasPermissions.canRead && this.canvasPermissions.canWrite; } - if (this.isProcessGroup(selection)) { - return true; + // disable configuration if there are multiple components selected + if (selection.size() > 1) { + return false; } + if (!this.canRead(selection) || !this.canModify(selection)) { return false; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/state/flow/flow.actions.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/state/flow/flow.actions.ts index fe727f2291..c6320ae0cd 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/state/flow/flow.actions.ts +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/state/flow/flow.actions.ts @@ -258,6 +258,11 @@ export const openEditConnectionDialog = createAction( props<{ request: EditConnectionDialogRequest }>() ); +export const openEditProcessGroupDialog = createAction( + '[Canvas] Open Edit Process Group Dialog', + props<{ request: EditComponentDialogRequest }>() +); + export const updateComponent = createAction('[Canvas] Update Component', props<{ request: UpdateComponentRequest }>()); export const updateComponentSuccess = createAction( diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/state/flow/flow.effects.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/state/flow/flow.effects.ts index c178858223..711ee0a3c0 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/state/flow/flow.effects.ts +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/state/flow/flow.effects.ts @@ -85,6 +85,7 @@ import { CreateConnection } from '../../ui/connection/create-connection/create-c import { EditConnectionComponent } from '../../ui/connection/edit-connection/edit-connection.component'; import { OkDialog } from '../../../../ui/common/ok-dialog/ok-dialog.component'; import { GroupComponents } from '../../ui/process-group/group-components/group-components.component'; +import { EditProcessGroup } from '../../ui/process-group/edit-process-group/edit-process-group.component'; @Injectable() export class FlowEffects { @@ -651,6 +652,8 @@ export class FlowEffects { return of(FlowActions.openEditProcessorDialog({ request })); case ComponentType.Connection: return of(FlowActions.openEditConnectionDialog({ request })); + case ComponentType.ProcessGroup: + return of(FlowActions.openEditProcessGroupDialog({ request })); case ComponentType.InputPort: case ComponentType.OutputPort: return of(FlowActions.openEditPortDialog({ request })); @@ -773,18 +776,20 @@ export class FlowEffects { // TODO - inline service creation... - editDialogReference.componentInstance.editProcessor.pipe(take(1)).subscribe((payload: any) => { - this.store.dispatch( - FlowActions.updateProcessor({ - request: { - id: request.entity.id, - uri: request.uri, - type: request.type, - payload - } - }) - ); - }); + editDialogReference.componentInstance.editProcessor + .pipe(takeUntil(editDialogReference.afterClosed())) + .subscribe((payload: any) => { + this.store.dispatch( + FlowActions.updateProcessor({ + request: { + id: request.entity.id, + uri: request.uri, + type: request.type, + payload + } + }) + ); + }); editDialogReference.afterClosed().subscribe(() => { this.store.dispatch(FlowActions.clearFlowApiError()); @@ -869,6 +874,61 @@ export class FlowEffects { { dispatch: false } ); + openEditProcessGroupDialog$ = createEffect( + () => + this.actions$.pipe( + ofType(FlowActions.openEditProcessGroupDialog), + map((action) => action.request), + switchMap((action) => + this.flowService.getParameterContexts().pipe( + take(1), + map((response) => [action, response.parameterContexts]) + ) + ), + tap(([request, parameterContexts]) => { + const editDialogReference = this.dialog.open(EditProcessGroup, { + data: request, + panelClass: 'large-dialog' + }); + + editDialogReference.componentInstance.saving$ = this.store.select(selectSaving); + editDialogReference.componentInstance.parameterContexts = parameterContexts; + + editDialogReference.componentInstance.editProcessGroup + .pipe(takeUntil(editDialogReference.afterClosed())) + .subscribe((payload: any) => { + this.store.dispatch( + FlowActions.updateComponent({ + request: { + id: request.entity.id, + uri: request.uri, + type: request.type, + payload + } + }) + ); + }); + + editDialogReference.afterClosed().subscribe(() => { + this.store.dispatch(FlowActions.clearFlowApiError()); + this.store.dispatch( + FlowActions.selectComponents({ + request: { + components: [ + { + id: request.entity.id, + componentType: request.type + } + ] + } + }) + ); + }); + }) + ), + { dispatch: false } + ); + updateComponent$ = createEffect(() => this.actions$.pipe( ofType(FlowActions.updateComponent), diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/canvas/context-menu/context-menu.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/canvas/context-menu/context-menu.component.ts index c75778bcae..a21ab2194c 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/canvas/context-menu/context-menu.component.ts +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/canvas/context-menu/context-menu.component.ts @@ -286,15 +286,18 @@ export class ContextMenu implements OnInit { clazz: 'fa fa-gear', text: 'Configure', action: function (store: Store, selection: any) { - const selectionData = selection.datum(); - store.dispatch( - navigateToEditComponent({ - request: { - type: selectionData.type, - id: selectionData.id - } - }) - ); + // TODO - when selection is empty support configuring the current Process Group + if (!selection.empty()) { + const selectionData = selection.datum(); + store.dispatch( + navigateToEditComponent({ + request: { + type: selectionData.type, + id: selectionData.id + } + }) + ); + } } }, { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.html b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.html new file mode 100644 index 0000000000..c332a3b2fd --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.html @@ -0,0 +1,162 @@ + + +

Edit Process Group

+
+ + + +
+
+
+ + Name + + +
+
+ + Parameter Context + + + + {{ option.text }} + + + {{ option.text }} + + + + +
+
+ + Apply Recursively + +
+
+ + Execution Engine + + + + {{ option.text }} + + + + +
+
+ + Process Group FlowFile Concurrency + + + + {{ option.text }} + + + + +
+
+ + Process Group Outbound Policy + + + + {{ option.text }} + + + + +
+
+
+
+ + Default FlowFile Expiration + + +
+
+ + Default Back Pressure Object Threshold + + +
+
+ + Default Back Pressure Data Size Threshold + + +
+
+ + Log File Suffix + + +
+
+
+
+ +
+ + Comments + + +
+
+
+
+ + + + +
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.scss b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.scss new file mode 100644 index 0000000000..50f47c8d69 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.scss @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@use '@angular/material' as mat; + +.process-group-edit-form { + @include mat.button-density(-1); + + .mdc-dialog__content { + padding: 0 16px; + font-size: 14px; + + .tab-content { + height: 475px; + overflow-y: auto; + } + } + + .mat-mdc-form-field { + width: 100%; + } +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.spec.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.spec.ts new file mode 100644 index 0000000000..eb8744dd76 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.spec.ts @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EditProcessGroup } from './edit-process-group.component'; +import { EditComponentDialogRequest } from '../../../state/flow'; +import { MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { ComponentType } from '../../../../../state/shared'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; + +describe('EditProcessGroup', () => { + let component: EditProcessGroup; + let fixture: ComponentFixture; + + const parameterContextId: string = '95d509b9-018b-1000-daff-b7957ea7934f'; + const data: any = { + type: 'ProcessGroup', + uri: 'https://localhost:4200/nifi-api/process-groups/162380af-018c-1000-a7eb-f5d06f77168b', + entity: { + revision: { + clientId: 'de5d3be3-05be-4ba5-bc42-729e7a4b00c4', + version: 14 + }, + id: '162380af-018c-1000-a7eb-f5d06f77168b', + uri: 'https://localhost:4200/nifi-api/process-groups/162380af-018c-1000-a7eb-f5d06f77168b', + position: { + x: 446, + y: 151 + }, + permissions: { + canRead: true, + canWrite: true + }, + bulletins: [], + component: { + id: '162380af-018c-1000-a7eb-f5d06f77168b', + parentGroupId: '1621f9d1-018c-1000-cb13-7eab94ffe23c', + position: { + x: 446, + y: 151 + }, + name: 'pg2', + comments: '', + flowfileConcurrency: 'UNBOUNDED', + flowfileOutboundPolicy: 'BATCH_OUTPUT', + defaultFlowFileExpiration: '0 sec', + defaultBackPressureObjectThreshold: 10000, + defaultBackPressureDataSizeThreshold: '1 GB', + parameterContext: { + id: parameterContextId + }, + executionEngine: 'INHERITED', + maxConcurrentTasks: 1, + statelessFlowTimeout: '1 min', + runningCount: 0, + stoppedCount: 0, + invalidCount: 0, + disabledCount: 0, + activeRemotePortCount: 0, + inactiveRemotePortCount: 0, + upToDateCount: 0, + locallyModifiedCount: 0, + staleCount: 0, + locallyModifiedAndStaleCount: 0, + syncFailureCount: 0, + localInputPortCount: 0, + localOutputPortCount: 0, + publicInputPortCount: 0, + publicOutputPortCount: 0, + statelessGroupScheduledState: 'STOPPED', + inputPortCount: 0, + outputPortCount: 0 + }, + runningCount: 0, + stoppedCount: 0, + invalidCount: 0, + disabledCount: 0, + activeRemotePortCount: 0, + inactiveRemotePortCount: 0, + upToDateCount: 0, + locallyModifiedCount: 0, + staleCount: 0, + locallyModifiedAndStaleCount: 0, + syncFailureCount: 0, + localInputPortCount: 0, + localOutputPortCount: 0, + publicInputPortCount: 0, + publicOutputPortCount: 0, + inputPortCount: 0, + outputPortCount: 0 + } + }; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [EditProcessGroup, BrowserAnimationsModule], + providers: [{ provide: MAT_DIALOG_DATA, useValue: data }] + }); + fixture = TestBed.createComponent(EditProcessGroup); + component = fixture.componentInstance; + component.parameterContexts = [ + { + revision: { + version: 0 + }, + id: parameterContextId, + uri: '', + permissions: { + canRead: true, + canWrite: true + }, + component: { + name: 'params 2', + description: '', + parameters: [], + boundProcessGroups: [], + inheritedParameterContexts: [], + id: '95d509b9-018b-1000-daff-b7957ea7934f' + } + } + ]; + + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('verify parameter context value', () => { + expect(component.parameterContextsOptions.length).toEqual(2); + expect(component.editProcessGroupForm.get('parameterContext')?.value).toEqual(parameterContextId); + }); +}); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.ts new file mode 100644 index 0000000000..cf4f7040f0 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/canvas/ui/process-group/edit-process-group/edit-process-group.component.ts @@ -0,0 +1,227 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component, EventEmitter, Inject, Input, Output } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; +import { FormBuilder, FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; +import { MatInputModule } from '@angular/material/input'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatButtonModule } from '@angular/material/button'; +import { AsyncPipe, NgForOf, NgIf } from '@angular/common'; +import { MatTabsModule } from '@angular/material/tabs'; +import { MatOptionModule } from '@angular/material/core'; +import { MatSelectModule } from '@angular/material/select'; +import { Observable } from 'rxjs'; +import { SelectOption, TextTipInput } from '../../../../../state/shared'; +import { Client } from '../../../../../service/client.service'; +import { EditComponentDialogRequest } from '../../../state/flow'; +import { PropertyTable } from '../../../../../ui/common/property-table/property-table.component'; +import { NifiSpinnerDirective } from '../../../../../ui/common/spinner/nifi-spinner.directive'; +import { NifiTooltipDirective } from '../../../../../ui/common/tooltips/nifi-tooltip.directive'; +import { TextTip } from '../../../../../ui/common/tooltips/text-tip/text-tip.component'; +import { ParameterContextEntity } from '../../../../parameter-contexts/state/parameter-context-listing'; +import { ControllerServiceTable } from '../../../../../ui/common/controller-service/controller-service-table/controller-service-table.component'; + +@Component({ + selector: 'edit-process-group', + standalone: true, + templateUrl: './edit-process-group.component.html', + imports: [ + ReactiveFormsModule, + MatDialogModule, + MatInputModule, + MatCheckboxModule, + MatButtonModule, + NgIf, + MatTabsModule, + MatOptionModule, + MatSelectModule, + NgForOf, + AsyncPipe, + PropertyTable, + NifiSpinnerDirective, + NifiTooltipDirective, + FormsModule, + ControllerServiceTable + ], + styleUrls: ['./edit-process-group.component.scss'] +}) +export class EditProcessGroup { + @Input() set parameterContexts(parameterContexts: ParameterContextEntity[]) { + parameterContexts.forEach((parameterContext) => { + if (parameterContext.permissions.canRead) { + this.parameterContextsOptions.push({ + text: parameterContext.component.name, + value: parameterContext.id, + description: parameterContext.component.description + }); + } + }); + + if (this.request.entity.component.parameterContext) { + this.editProcessGroupForm.addControl( + 'parameterContext', + new FormControl(this.request.entity.component.parameterContext.id) + ); + } else { + this.editProcessGroupForm.addControl('parameterContext', new FormControl(null)); + } + } + @Input() saving$!: Observable; + @Output() editProcessGroup: EventEmitter = new EventEmitter(); + + protected readonly TextTip = TextTip; + + editProcessGroupForm: FormGroup; + parameterContextsOptions: SelectOption[] = []; + + executionEngineOptions: SelectOption[] = [ + { + text: 'Inherited', + value: 'INHERITED', + description: 'Use whichever Execution Engine the parent Process Group is configured to use.' + }, + { + text: 'Standard', + value: 'STANDARD', + description: 'Use the Standard NiFi Execution Engine. See the User Guide for additional details.' + }, + { + text: 'Stateless', + value: 'STATELESS', + description: + 'Run the dataflow using the Stateless Execution Engine. See the User Guide for additional details.' + } + ]; + + flowfileConcurrencyOptions: SelectOption[] = [ + { + text: 'Single FlowFile Per Node', + value: 'SINGLE_FLOWFILE_PER_NODE', + description: + 'Only a single FlowFile is to be allowed to enter the Process Group at a time on each node in the cluster. While that FlowFile may be split into many or ' + + 'spawn many children, no additional FlowFiles will be allowed to enter the Process Group through a Local Input Port until the previous FlowFile ' + + '- and all of its child/descendent FlowFiles - have been processed.' + }, + { + text: 'Single Batch Per Node', + value: 'SINGLE_BATCH_PER_NODE', + description: + 'When an Input Port pulls a FlowFile into the Process Group, FlowFiles will continue to be ingested into the Process Group until all input queues ' + + 'have been emptied. At that point, no additional FlowFiles will be allowed to enter the Process Group through a Local Input Port until the entire batch ' + + 'of FlowFiles has been processed.' + }, + { + text: 'Unbounded', + value: 'UNBOUNDED', + description: 'The number of FlowFiles that can be processed concurrently is unbounded.' + } + ]; + + flowfileOutboundPolicyOptions: SelectOption[] = [ + { + text: 'Stream When Available', + value: 'STREAM_WHEN_AVAILABLE', + description: + 'FlowFiles that are queued up to be transferred out of a Process Group by an Output Port will be transferred out ' + + 'of the Process Group as soon as they are available.' + }, + { + text: 'Batch Output', + value: 'BATCH_OUTPUT', + description: + 'FlowFiles that are queued up to be transferred out of a Process Group by an Output Port will remain queued until ' + + 'all FlowFiles in the Process Group are ready to be transferred out of the group. The FlowFiles will then be transferred ' + + 'out of the group. This setting will be ignored if the FlowFile Concurrency is Unbounded.' + } + ]; + + constructor( + @Inject(MAT_DIALOG_DATA) public request: EditComponentDialogRequest, + private formBuilder: FormBuilder, + private client: Client + ) { + this.parameterContextsOptions.push({ + text: 'No parameter context', + value: null + }); + + this.editProcessGroupForm = this.formBuilder.group({ + name: new FormControl(request.entity.component.name, Validators.required), + applyParameterContextRecursively: new FormControl(false), + executionEngine: new FormControl(request.entity.component.executionEngine, Validators.required), + flowfileConcurrency: new FormControl(request.entity.component.flowfileConcurrency, Validators.required), + flowfileOutboundPolicy: new FormControl( + request.entity.component.flowfileOutboundPolicy, + Validators.required + ), + defaultFlowFileExpiration: new FormControl( + request.entity.component.defaultFlowFileExpiration, + Validators.required + ), + defaultBackPressureObjectThreshold: new FormControl( + request.entity.component.defaultBackPressureObjectThreshold, + Validators.required + ), + defaultBackPressureDataSizeThreshold: new FormControl( + request.entity.component.defaultBackPressureDataSizeThreshold, + Validators.required + ), + logFileSuffix: new FormControl(request.entity.component.logFileSuffix), + comments: new FormControl(request.entity.component.comments) + }); + } + + getSelectOptionTipData(option: SelectOption): TextTipInput { + return { + // @ts-ignore + text: option.description + }; + } + + submitForm() { + let updateStrategy: string = 'DIRECT_CHILDREN'; + if (this.editProcessGroupForm.get('applyParameterContextRecursively')?.value) { + updateStrategy = 'ALL_DESCENDANTS'; + } + + const payload: any = { + revision: this.client.getRevision(this.request.entity), + processGroupUpdateStrategy: updateStrategy, + component: { + id: this.request.entity.id, + name: this.editProcessGroupForm.get('name')?.value, + executionEngine: this.editProcessGroupForm.get('executionEngine')?.value, + flowfileConcurrency: this.editProcessGroupForm.get('flowfileConcurrency')?.value, + flowfileOutboundPolicy: this.editProcessGroupForm.get('flowfileOutboundPolicy')?.value, + defaultFlowFileExpiration: this.editProcessGroupForm.get('defaultFlowFileExpiration')?.value, + defaultBackPressureObjectThreshold: this.editProcessGroupForm.get('defaultBackPressureObjectThreshold') + ?.value, + defaultBackPressureDataSizeThreshold: this.editProcessGroupForm.get( + 'defaultBackPressureDataSizeThreshold' + )?.value, + logFileSuffix: this.editProcessGroupForm.get('logFileSuffix')?.value, + parameterContext: { + id: this.editProcessGroupForm.get('parameterContext')?.value + }, + comments: this.editProcessGroupForm.get('comments')?.value + } + }; + + this.editProcessGroup.next(payload); + } +}