This is an automated email from the ASF dual-hosted git repository.

mcgilman pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 14fcc42d16 [NIFI-12758] create remote process group (#8376)
14fcc42d16 is described below

commit 14fcc42d161a189b1cb41f5398066e19b7824689
Author: Scott Aslan <scottyas...@users.noreply.github.com>
AuthorDate: Mon Feb 12 15:27:14 2024 -0500

    [NIFI-12758] create remote process group (#8376)
    
    * [NIFI-12758] create remote process group
    
    * address review feedback
    
    * update unit test
    
    This closes #8376
---
 .../main/nifi/src/app/_app.component-theme.scss    |   2 -
 .../pages/flow-designer/service/flow.service.ts    |  27 +++++
 .../pages/flow-designer/state/flow/flow.actions.ts |  11 ++
 .../pages/flow-designer/state/flow/flow.effects.ts |  44 ++++++++
 .../app/pages/flow-designer/state/flow/index.ts    |  12 +++
 ...reate-remote-process-group.component-theme.scss |  30 ++++++
 .../create-remote-process-group.component.html     | 115 +++++++++++++++++++++
 .../create-remote-process-group.component.scss     |  26 +++++
 .../create-remote-process-group.component.spec.ts  |  57 ++++++++++
 .../create-remote-process-group.component.ts       | 110 ++++++++++++++++++++
 .../src/main/nifi/src/styles.scss                  |   5 +-
 11 files changed, 436 insertions(+), 3 deletions(-)

diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/_app.component-theme.scss
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/_app.component-theme.scss
index b2f43cc03f..b3f95a0968 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/_app.component-theme.scss
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/_app.component-theme.scss
@@ -26,7 +26,6 @@
     // Get the color palette from the color-config.
     $primary-palette: map.get($color-config, 'primary');
     $accent-palette: map.get($color-config, 'accent');
-    $warn-palette: map.get($color-config, 'warn');
     $canvas-primary-palette: map.get($canvas-color-config, 'primary');
     $canvas-accent-palette: map.get($canvas-color-config, 'accent');
 
@@ -34,7 +33,6 @@
     $primary-palette-300: mat.get-color-from-palette($primary-palette, 300);
     $primary-palette-500: mat.get-color-from-palette($primary-palette, 500);
     $accent-palette-A400: mat.get-color-from-palette($accent-palette, 'A400');
-    $warn-palette-500: mat.get-color-from-palette($warn-palette, 500);
     $canvas-primary-palette-A200: 
mat.get-color-from-palette($canvas-primary-palette, 'A200');
     $canvas-accent-palette-500: 
mat.get-color-from-palette($canvas-accent-palette, 500);
 
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/flow.service.ts
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/flow.service.ts
index 818e802663..3222612af5 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/flow.service.ts
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/flow.service.ts
@@ -25,6 +25,7 @@ import {
     CreatePortRequest,
     CreateProcessGroupRequest,
     CreateProcessorRequest,
+    CreateRemoteProcessGroupRequest,
     DeleteComponentRequest,
     ProcessGroupRunStatusRequest,
     ReplayLastProvenanceEventRequest,
@@ -158,6 +159,32 @@ export class FlowService implements 
PropertyDescriptorRetriever {
         return 
this.httpClient.post(`${FlowService.API}/process-groups/${processGroupId}/process-groups`,
 payload);
     }
 
+    createRemoteProcessGroup(
+        processGroupId = 'root',
+        createRemoteProcessGroup: CreateRemoteProcessGroupRequest
+    ): Observable<any> {
+        const payload: any = {
+            revision: createRemoteProcessGroup.revision,
+            component: {
+                position: createRemoteProcessGroup.position,
+                targetUris: createRemoteProcessGroup.targetUris,
+                transportProtocol: createRemoteProcessGroup.transportProtocol,
+                localNetworkInterface: 
createRemoteProcessGroup.localNetworkInterface,
+                proxyHost: createRemoteProcessGroup.proxyHost,
+                proxyPort: createRemoteProcessGroup.proxyPort,
+                proxyUser: createRemoteProcessGroup.proxyUser,
+                proxyPassword: createRemoteProcessGroup.proxyPassword,
+                communicationsTimeout: 
createRemoteProcessGroup.communicationsTimeout,
+                yieldDuration: createRemoteProcessGroup.yieldDuration
+            }
+        };
+
+        return this.httpClient.post(
+            
`${FlowService.API}/process-groups/${processGroupId}/remote-process-groups`,
+            payload
+        );
+    }
+
     uploadProcessGroup(processGroupId = 'root', uploadProcessGroup: 
UploadProcessGroupRequest): Observable<any> {
         const payload = new FormData();
         payload.append('id', processGroupId);
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/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/flow-designer/state/flow/flow.actions.ts
index 8b79c0bcc8..0b2bd220e0 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/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/flow-designer/state/flow/flow.actions.ts
@@ -24,6 +24,7 @@ import {
     CreateConnectionDialogRequest,
     CreateConnectionRequest,
     CreatePortRequest,
+    CreateRemoteProcessGroupRequest,
     CreateProcessGroupDialogRequest,
     CreateProcessGroupRequest,
     CreateProcessorRequest,
@@ -210,11 +211,21 @@ export const createFunnel = createAction(
 
 export const createLabel = createAction(`${CANVAS_PREFIX} Create Label`, 
props<{ request: CreateComponentRequest }>());
 
+export const createRemoteProcessGroup = createAction(
+    `${CANVAS_PREFIX} Create Remote Process Group`,
+    props<{ request: CreateRemoteProcessGroupRequest }>()
+);
+
 export const openNewProcessGroupDialog = createAction(
     `${CANVAS_PREFIX} Open New Process Group Dialog`,
     props<{ request: CreateProcessGroupDialogRequest }>()
 );
 
+export const openNewRemoteProcessGroupDialog = createAction(
+    `${CANVAS_PREFIX} Open New Remote Process Group Dialog`,
+    props<{ request: CreateComponentRequest }>()
+);
+
 export const createProcessGroup = createAction(
     `${CANVAS_PREFIX} Create Process Group`,
     props<{ request: CreateProcessGroupRequest }>()
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/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/flow-designer/state/flow/flow.effects.ts
index d77eb0cc08..1554f2f3a4 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/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/flow-designer/state/flow/flow.effects.ts
@@ -80,6 +80,7 @@ import { NiFiState } from '../../../../state';
 import { CreateProcessor } from 
'../../ui/canvas/items/processor/create-processor/create-processor.component';
 import { EditProcessor } from 
'../../ui/canvas/items/processor/edit-processor/edit-processor.component';
 import { BirdseyeView } from '../../service/birdseye-view.service';
+import { CreateRemoteProcessGroup } from 
'../../ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-process-group.component';
 import { CreateProcessGroup } from 
'../../ui/canvas/items/process-group/create-process-group/create-process-group.component';
 import { CreateConnection } from 
'../../ui/canvas/items/connection/create-connection/create-connection.component';
 import { EditConnectionComponent } from 
'../../ui/canvas/items/connection/edit-connection/edit-connection.component';
@@ -222,6 +223,8 @@ export class FlowEffects {
                             }),
                             catchError((error) => 
of(FlowActions.flowApiError({ error: error.error })))
                         );
+                    case ComponentType.RemoteProcessGroup:
+                        return 
of(FlowActions.openNewRemoteProcessGroupDialog({ request }));
                     case ComponentType.Funnel:
                         return of(FlowActions.createFunnel({ request }));
                     case ComponentType.Label:
@@ -293,6 +296,47 @@ export class FlowEffects {
         )
     );
 
+    openNewRemoteProcessGroupDialog$ = createEffect(
+        () =>
+            this.actions$.pipe(
+                ofType(FlowActions.openNewRemoteProcessGroupDialog),
+                map((action) => action.request),
+                tap((request) => {
+                    this.dialog
+                        .open(CreateRemoteProcessGroup, {
+                            data: request,
+                            panelClass: 'large-dialog'
+                        })
+                        .afterClosed()
+                        .subscribe(() => {
+                            this.store.dispatch(FlowActions.setDragging({ 
dragging: false }));
+                        });
+                })
+            ),
+        { dispatch: false }
+    );
+
+    createRemoteProcessGroup$ = createEffect(() =>
+        this.actions$.pipe(
+            ofType(FlowActions.createRemoteProcessGroup),
+            map((action) => action.request),
+            concatLatestFrom(() => 
this.store.select(selectCurrentProcessGroupId)),
+            switchMap(([request, processGroupId]) =>
+                from(this.flowService.createRemoteProcessGroup(processGroupId, 
request)).pipe(
+                    map((response) =>
+                        FlowActions.createComponentSuccess({
+                            response: {
+                                type: request.type,
+                                payload: response
+                            }
+                        })
+                    ),
+                    catchError((error) => of(FlowActions.flowApiError({ error: 
error.error })))
+                )
+            )
+        )
+    );
+
     openNewProcessGroupDialog$ = createEffect(
         () =>
             this.actions$.pipe(
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/index.ts
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/index.ts
index bb4f9ddb70..f9b0536007 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/index.ts
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/index.ts
@@ -219,6 +219,18 @@ export interface UploadProcessGroupRequest extends 
CreateComponentRequest {
     flowDefinition: File;
 }
 
+export interface CreateRemoteProcessGroupRequest extends 
CreateComponentRequest {
+    targetUris: string;
+    transportProtocol: string;
+    localNetworkInterface: string;
+    proxyHost: string;
+    proxyPort: string;
+    proxyUser: string;
+    proxyPassword: string;
+    communicationsTimeout: string;
+    yieldDuration: string;
+}
+
 export interface CreatePortRequest extends CreateComponentRequest {
     name: string;
     allowRemoteAccess: boolean;
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/_create-remote-process-group.component-theme.scss
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/_create-remote-process-group.component-theme.scss
new file mode 100644
index 0000000000..4fa7321840
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/_create-remote-process-group.component-theme.scss
@@ -0,0 +1,30 @@
+/*
+ * 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 'sass:map';
+@use '@angular/material' as mat;
+
+@mixin nifi-theme($theme) {
+    // Get the color config from the theme.
+    $color-config: mat.get-color-config($theme);
+
+    // Get the color palette from the color-config.
+    $accent-palette: map.get($color-config, 'accent');
+
+    // Get hues from palette
+    $accent-palette-A400: mat.get-color-from-palette($accent-palette, 'A400');
+}
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-process-group.component.html
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-process-group.component.html
new file mode 100644
index 0000000000..2e2f38306c
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-process-group.component.html
@@ -0,0 +1,115 @@
+<!--
+  ~ 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.
+  -->
+
+<h2 mat-dialog-title>Create Remote Process Group</h2>
+<form class="create-remote-process-group-form" 
[formGroup]="createRemoteProcessGroupForm">
+    <error-banner></error-banner>
+    <mat-dialog-content>
+        <div class="tab-content py-4 flex gap-x-4">
+            <div class="w-full">
+                <mat-form-field>
+                    <mat-label>URLs</mat-label>
+                    <input matInput formControlName="urls" type="text" 
placeholder="https://remotehost:8443/nifi"; />
+                </mat-form-field>
+            </div>
+        </div>
+        <div class="flex gap-x-4">
+            <div class="w-full">
+                <mat-form-field>
+                    <mat-label>Transport Protocol</mat-label>
+                    <mat-select formControlName="transportProtocol">
+                        <mat-option
+                            value="RAW"
+                            nifiTooltip
+                            [tooltipComponentType]="TextTip"
+                            [tooltipInputData]="getOptionTipData('RAW')"
+                            [delayClose]="false">
+                            RAW
+                        </mat-option>
+                        <mat-option
+                            value="HTTP"
+                            nifiTooltip
+                            [tooltipComponentType]="TextTip"
+                            [tooltipInputData]="getOptionTipData('HTTP')"
+                            [delayClose]="false">
+                            HTTP
+                        </mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+            <div class="w-full">
+                <mat-form-field>
+                    <mat-label>Local Network Interface</mat-label>
+                    <input matInput formControlName="localNetworkInterface" 
type="text" />
+                </mat-form-field>
+            </div>
+        </div>
+        <div class="flex gap-x-4">
+            <div class="w-full">
+                <mat-form-field>
+                    <mat-label>HTTP Proxy Server Hostname</mat-label>
+                    <input matInput formControlName="httpProxyServerHostname" 
type="text" />
+                </mat-form-field>
+            </div>
+            <div class="w-full">
+                <mat-form-field>
+                    <mat-label>HTTP Proxy Server Port</mat-label>
+                    <input matInput formControlName="httpProxyServerPort" 
type="text" />
+                </mat-form-field>
+            </div>
+        </div>
+        <div class="flex gap-x-4">
+            <div class="w-full">
+                <mat-form-field>
+                    <mat-label>HTTP Proxy User</mat-label>
+                    <input matInput formControlName="httpProxyUser" 
type="text" />
+                </mat-form-field>
+            </div>
+            <div class="w-full">
+                <mat-form-field>
+                    <mat-label>HTTP Proxy Password</mat-label>
+                    <input matInput formControlName="httpProxyPassword" 
type="text" />
+                </mat-form-field>
+            </div>
+        </div>
+        <div class="flex gap-x-4">
+            <div class="w-full">
+                <mat-form-field>
+                    <mat-label>Communications Timeout</mat-label>
+                    <input matInput formControlName="communicationsTimeout" 
type="text" />
+                </mat-form-field>
+            </div>
+            <div class="w-full">
+                <mat-form-field>
+                    <mat-label>Yield Duration</mat-label>
+                    <input matInput formControlName="yieldDuration" 
type="text" />
+                </mat-form-field>
+            </div>
+        </div>
+    </mat-dialog-content>
+    <mat-dialog-actions align="end" *ngIf="{ value: (saving$ | async)! } as 
saving">
+        <button color="primary" mat-stroked-button 
mat-dialog-close>Cancel</button>
+        <button
+            [disabled]="!createRemoteProcessGroupForm.dirty || 
createRemoteProcessGroupForm.invalid || saving.value"
+            type="button"
+            color="primary"
+            (click)="createRemoteProcessGroup()"
+            mat-raised-button>
+            <span *nifiSpinner="saving.value">Add</span>
+        </button>
+    </mat-dialog-actions>
+</form>
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-process-group.component.scss
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-process-group.component.scss
new file mode 100644
index 0000000000..72ad7a4fb1
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-process-group.component.scss
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+.create-remote-process-group-form {
+    @include mat.button-density(-1);
+
+    .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/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-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/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-process-group.component.spec.ts
new file mode 100644
index 0000000000..d2ffc980de
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-process-group.component.spec.ts
@@ -0,0 +1,57 @@
+/*
+ * 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 { CreateRemoteProcessGroup } from 
'./create-remote-process-group.component';
+import { MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { ComponentType } from '../../../../../../../state/shared';
+import { provideMockStore } from '@ngrx/store/testing';
+import { initialState } from '../../../../../state/flow/flow.reducer';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { CreateComponentRequest } from '../../../../../state/flow';
+
+describe('CreateRemoteProcessGroup', () => {
+    let component: CreateRemoteProcessGroup;
+    let fixture: ComponentFixture<CreateRemoteProcessGroup>;
+
+    const data: CreateComponentRequest = {
+        revision: {
+            clientId: 'a6482293-7fe8-43b4-8ab4-ee95b3b27721',
+            version: 0
+        },
+        type: ComponentType.ProcessGroup,
+        position: {
+            x: -4,
+            y: -698.5
+        }
+    };
+
+    beforeEach(() => {
+        TestBed.configureTestingModule({
+            imports: [CreateRemoteProcessGroup, BrowserAnimationsModule],
+            providers: [{ provide: MAT_DIALOG_DATA, useValue: data }, 
provideMockStore({ initialState })]
+        });
+        fixture = TestBed.createComponent(CreateRemoteProcessGroup);
+        component = fixture.componentInstance;
+        fixture.detectChanges();
+    });
+
+    it('should create', () => {
+        expect(component).toBeTruthy();
+    });
+});
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-process-group.component.ts
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-process-group.component.ts
new file mode 100644
index 0000000000..c8a77e22a9
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-process-group.component.ts
@@ -0,0 +1,110 @@
+/*
+ * 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, Inject } from '@angular/core';
+import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
+import { Store } from '@ngrx/store';
+import { CanvasState } from '../../../../../state';
+import { createRemoteProcessGroup } from 
'../../../../../state/flow/flow.actions';
+import { TextTipInput } from '../../../../../../../state/shared';
+import { selectSaving } from '../../../../../state/flow/flow.selectors';
+import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
+import { ErrorBanner } from 
'../../../../../../../ui/common/error-banner/error-banner.component';
+import { MatButtonModule } from '@angular/material/button';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatOptionModule } from '@angular/material/core';
+import { MatSelectModule } from '@angular/material/select';
+import { NifiSpinnerDirective } from 
'../../../../../../../ui/common/spinner/nifi-spinner.directive';
+import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators 
} from '@angular/forms';
+import { TextTip } from 
'../../../../../../../ui/common/tooltips/text-tip/text-tip.component';
+import { NifiTooltipDirective } from 
'../../../../../../../ui/common/tooltips/nifi-tooltip.directive';
+import { MatIconModule } from '@angular/material/icon';
+import { CreateComponentRequest } from '../../../../../state/flow';
+
+@Component({
+    selector: 'create-process-group',
+    standalone: true,
+    imports: [
+        AsyncPipe,
+        ErrorBanner,
+        MatButtonModule,
+        MatDialogModule,
+        MatFormFieldModule,
+        MatInputModule,
+        NgIf,
+        NifiSpinnerDirective,
+        ReactiveFormsModule,
+        MatOptionModule,
+        MatSelectModule,
+        NgForOf,
+        NifiTooltipDirective,
+        MatIconModule
+    ],
+    templateUrl: './create-remote-process-group.component.html',
+    styleUrls: ['./create-remote-process-group.component.scss']
+})
+export class CreateRemoteProcessGroup {
+    saving$ = this.store.select(selectSaving);
+
+    protected readonly TextTip = TextTip;
+
+    createRemoteProcessGroupForm: FormGroup;
+
+    constructor(
+        @Inject(MAT_DIALOG_DATA) private dialogRequest: CreateComponentRequest,
+        private formBuilder: FormBuilder,
+        private store: Store<CanvasState>
+    ) {
+        this.createRemoteProcessGroupForm = this.formBuilder.group({
+            urls: new FormControl('', Validators.required),
+            transportProtocol: new FormControl('RAW', Validators.required),
+            localNetworkInterface: new FormControl(''),
+            httpProxyServerHostname: new FormControl(''),
+            httpProxyServerPort: new FormControl(''),
+            httpProxyUser: new FormControl(''),
+            httpProxyPassword: new FormControl(''),
+            communicationsTimeout: new FormControl('30 sec', 
Validators.required),
+            yieldDuration: new FormControl('10 sec', Validators.required)
+        });
+    }
+
+    getOptionTipData(tip: string): TextTipInput {
+        return {
+            text: tip
+        };
+    }
+
+    createRemoteProcessGroup(): void {
+        this.store.dispatch(
+            createRemoteProcessGroup({
+                request: {
+                    ...this.dialogRequest,
+                    targetUris: 
this.createRemoteProcessGroupForm.get('urls')?.value,
+                    transportProtocol: 
this.createRemoteProcessGroupForm.get('transportProtocol')?.value,
+                    localNetworkInterface: 
this.createRemoteProcessGroupForm.get('localNetworkInterface')?.value,
+                    proxyHost: 
this.createRemoteProcessGroupForm.get('httpProxyServerHostname')?.value,
+                    proxyPort: 
this.createRemoteProcessGroupForm.get('httpProxyServerPort')?.value,
+                    proxyUser: 
this.createRemoteProcessGroupForm.get('httpProxyUser')?.value,
+                    proxyPassword: 
this.createRemoteProcessGroupForm.get('httpProxyPassword')?.value,
+                    communicationsTimeout: 
this.createRemoteProcessGroupForm.get('communicationsTimeout')?.value,
+                    yieldDuration: 
this.createRemoteProcessGroupForm.get('yieldDuration')?.value
+                }
+            })
+        );
+    }
+}
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/styles.scss
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/styles.scss
index f45fd9af17..524caae52f 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/styles.scss
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/styles.scss
@@ -38,6 +38,7 @@
 @use 'app/pages/flow-designer/ui/canvas/header/search/search.component-theme' 
as search;
 @use 
'app/pages/flow-designer/ui/canvas/items/connection/prioritizers/prioritizers.component-theme'
 as prioritizers;
 @use 
'app/pages/flow-designer/ui/canvas/items/process-group/create-process-group/create-process-group.component-theme'
 as create-process-group;
+@use 
'app/pages/flow-designer/ui/canvas/items/remote-process-group/create-remote-process-group/create-remote-process-group.component-theme'
 as create-remote-process-group;
 @use 'app/pages/flow-designer/ui/common/banner/banner.component-theme' as 
banner;
 @use 
'app/pages/flow-designer/ui/controller-service/controller-services.component-theme'
 as controller-service;
 @use 'app/pages/login/feature/login.component-theme' as login;
@@ -384,7 +385,7 @@ $appFontPath: '~roboto-fontface/fonts';
     .large-dialog {
         max-height: 72%;
         max-width: 55%;
-        min-height: 560px;
+        min-height: 520px;
         min-width: 760px;
     }
 
@@ -490,6 +491,7 @@ $appFontPath: '~roboto-fontface/fonts';
 @include search.nifi-theme($material-theme-light, $nifi-canvas-theme-light);
 @include prioritizers.nifi-theme($material-theme-light, 
$nifi-canvas-theme-light);
 @include create-process-group.nifi-theme($material-theme-light);
+@include create-remote-process-group.nifi-theme($material-theme-light);
 @include login.nifi-theme($material-theme-light, $nifi-canvas-theme-light);
 @include login-form.nifi-theme($material-theme-light);
 @include provenance-event-table.nifi-theme($material-theme-light, 
$nifi-canvas-theme-light);
@@ -539,6 +541,7 @@ $appFontPath: '~roboto-fontface/fonts';
     @include search.nifi-theme($material-theme-dark, $nifi-canvas-theme-dark);
     @include prioritizers.nifi-theme($material-theme-dark, 
$nifi-canvas-theme-dark);
     @include create-process-group.nifi-theme($material-theme-dark);
+    @include create-remote-process-group.nifi-theme($material-theme-dark);
     @include login.nifi-theme($material-theme-dark, $nifi-canvas-theme-dark);
     @include login-form.nifi-theme($material-theme-dark);
     @include provenance-event-table.nifi-theme($material-theme-dark, 
$nifi-canvas-theme-dark);

Reply via email to