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/controller-service.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/controller-service.service.ts index cb3ffe42a6..9ef906c5f7 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/controller-service.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/controller-service.service.ts @@ -48,8 +48,8 @@ export class ControllerServiceService implements ControllerServiceCreator, Prope ); } - getBreadcrumbs(processGroupId: string): Observable { - return this.httpClient.get(`${ControllerServiceService.API}/flow/process-groups/${processGroupId}/breadcrumbs`); + getFlow(processGroupId: string): Observable { + return this.httpClient.get(`${ControllerServiceService.API}/flow/process-groups/${processGroupId}`); } getControllerService(id: string): Observable { 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/parameter-helper.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/parameter-helper.service.ts new file mode 100644 index 0000000000..e8b4e1417d --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/parameter-helper.service.ts @@ -0,0 +1,162 @@ +/* + * 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 { Injectable } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { catchError, EMPTY, filter, map, Observable, switchMap, take, takeUntil, tap } from 'rxjs'; +import { Store } from '@ngrx/store'; +import { HttpErrorResponse } from '@angular/common/http'; +import { NiFiState } from '../../../state'; +import { ParameterService } from './parameter.service'; +import { Client } from '../../../service/client.service'; +import { EditParameterRequest, EditParameterResponse, Parameter, ParameterEntity } from '../../../state/shared'; +import { EditParameterDialog } from '../../../ui/common/edit-parameter-dialog/edit-parameter-dialog.component'; +import { selectParameterSaving, selectParameterState } from '../state/parameter/parameter.selectors'; +import { ParameterState } from '../state/parameter'; +import * as ErrorActions from '../../../state/error/error.actions'; +import * as ParameterActions from '../state/parameter/parameter.actions'; +import { FlowService } from './flow.service'; + +@Injectable({ + providedIn: 'root' +}) +export class ParameterHelperService { + constructor( + private dialog: MatDialog, + private store: Store, + private flowService: FlowService, + private parameterService: ParameterService, + private client: Client + ) {} + + /** + * Returns a function that can be used to pass into a PropertyTable to retrieve available Parameters. + * + * @param parameterContextId the current Parameter Context id + */ + getParameters(parameterContextId: string): (sensitive: boolean) => Observable { + return (sensitive: boolean) => { + return this.flowService.getParameterContext(parameterContextId).pipe( + take(1), + catchError((errorResponse: HttpErrorResponse) => { + this.store.dispatch(ErrorActions.snackBarError({ error: errorResponse.error })); + + // consider the error handled and allow the user to reattempt the action + return EMPTY; + }), + map((response) => response.component.parameters), + map((parameterEntities) => { + return parameterEntities + .map((parameterEntity: ParameterEntity) => parameterEntity.parameter) + .filter((parameter: Parameter) => parameter.sensitive == sensitive); + }) + ); + }; + } + + /** + * Returns a function that can be used to pass into a PropertyTable to convert a Property into a Parameter, inline. + * + * @param parameterContextId the current Parameter Context id + */ + convertToParameter( + parameterContextId: string + ): (name: string, sensitive: boolean, value: string | null) => Observable { + return (name: string, sensitive: boolean, value: string | null) => { + return this.parameterService.getParameterContext(parameterContextId, false).pipe( + catchError((errorResponse: HttpErrorResponse) => { + this.store.dispatch(ErrorActions.snackBarError({ error: errorResponse.error })); + + // consider the error handled and allow the user to reattempt the action + return EMPTY; + }), + switchMap((parameterContextEntity) => { + const existingParameters: string[] = parameterContextEntity.component.parameters.map( + (parameterEntity: ParameterEntity) => parameterEntity.parameter.name + ); + const convertToParameterDialogRequest: EditParameterRequest = { + parameter: { + name, + value, + sensitive, + description: '' + }, + existingParameters + }; + const convertToParameterDialogReference = this.dialog.open(EditParameterDialog, { + data: convertToParameterDialogRequest, + panelClass: 'medium-dialog' + }); + + convertToParameterDialogReference.componentInstance.saving$ = + this.store.select(selectParameterSaving); + + convertToParameterDialogReference.componentInstance.cancel.pipe( + takeUntil(convertToParameterDialogReference.afterClosed()), + tap(() => ParameterActions.stopPollingParameterContextUpdateRequest()) + ); + + return convertToParameterDialogReference.componentInstance.editParameter.pipe( + takeUntil(convertToParameterDialogReference.afterClosed()), + switchMap((dialogResponse: EditParameterResponse) => { + this.store.dispatch( + ParameterActions.submitParameterContextUpdateRequest({ + request: { + id: parameterContextId, + payload: { + revision: this.client.getRevision(parameterContextEntity), + component: { + id: parameterContextEntity.id, + parameters: [{ parameter: dialogResponse.parameter }] + } + } + } + }) + ); + + return this.store.select(selectParameterState).pipe( + takeUntil(convertToParameterDialogReference.afterClosed()), + tap((parameterState: ParameterState) => { + if (parameterState.error) { + // if the convert to parameter sequence stores an error, + // throw it to avoid the completion mapping logic below + throw new Error(parameterState.error); + } + }), + filter((parameterState: ParameterState) => !parameterState.saving), + map(() => { + convertToParameterDialogReference.close(); + return `#{${dialogResponse.parameter.name}}`; + }), + catchError((error) => { + convertToParameterDialogReference.close(); + + // show the error in the snack and complete the edit to reset it's state + this.store.dispatch(ErrorActions.snackBarError({ error: error.message })); + this.store.dispatch(ParameterActions.editParameterContextComplete()); + + // consider the error handled and allow the user to reattempt the action + return EMPTY; + }) + ); + }) + ); + }) + ); + }; + } +} 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/controller-services/controller-services.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/controller-services/controller-services.actions.ts index 7dd7c9ff59..588801dbaa 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.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/controller-services/controller-services.actions.ts @@ -45,8 +45,8 @@ export const loadControllerServicesSuccess = createAction( props<{ response: LoadControllerServicesResponse }>() ); -export const controllerServicesApiError = createAction( - '[Controller Services] Load Controller Service Error', +export const controllerServicesBannerApiError = createAction( + '[Controller Services] Controller Services Banner Api Error', props<{ error: string }>() ); 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/controller-services/controller-services.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/controller-services/controller-services.effects.ts index 77742b1baa..2ad4ea44f9 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.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/controller-services/controller-services.effects.ts @@ -18,7 +18,7 @@ import { Injectable } from '@angular/core'; import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects'; import * as ControllerServicesActions from './controller-services.actions'; -import { catchError, combineLatest, filter, from, map, NEVER, of, switchMap, take, takeUntil, tap } from 'rxjs'; +import { catchError, combineLatest, from, map, of, switchMap, take, takeUntil, tap } from 'rxjs'; import { MatDialog } from '@angular/material/dialog'; import { Store } from '@ngrx/store'; import { NiFiState } from '../../../../state'; @@ -30,25 +30,24 @@ import { EditControllerService } from '../../../../ui/common/controller-service/ import { ComponentType, ControllerServiceReferencingComponent, - EditParameterRequest, - EditParameterResponse, - Parameter, - ParameterEntity, UpdateControllerServiceRequest } from '../../../../state/shared'; import { Router } from '@angular/router'; -import { ExtensionTypesService } from '../../../../service/extension-types.service'; -import { selectCurrentProcessGroupId, selectSaving } from './controller-services.selectors'; +import { + selectCurrentProcessGroupId, + selectParameterContext, + selectSaving, + selectStatus +} from './controller-services.selectors'; import { ControllerServiceService } from '../../service/controller-service.service'; -import { selectCurrentParameterContext } from '../flow/flow.selectors'; import { FlowService } from '../../service/flow.service'; -import { EditParameterDialog } from '../../../../ui/common/edit-parameter-dialog/edit-parameter-dialog.component'; -import { selectParameterSaving } from '../parameter/parameter.selectors'; -import * as ParameterActions from '../parameter/parameter.actions'; -import { ParameterService } from '../../service/parameter.service'; import { EnableControllerService } from '../../../../ui/common/controller-service/enable-controller-service/enable-controller-service.component'; import { DisableControllerService } from '../../../../ui/common/controller-service/disable-controller-service/disable-controller-service.component'; import { PropertyTableHelperService } from '../../../../service/property-table-helper.service'; +import * as ErrorActions from '../../../../state/error/error.actions'; +import { ErrorHelper } from '../../../../service/error-helper.service'; +import { HttpErrorResponse } from '@angular/common/http'; +import { ParameterHelperService } from '../../service/parameter-helper.service'; @Injectable() export class ControllerServicesEffects { @@ -58,39 +57,45 @@ export class ControllerServicesEffects { private client: Client, private controllerServiceService: ControllerServiceService, private flowService: FlowService, - private parameterService: ParameterService, - private extensionTypesService: ExtensionTypesService, + private errorHelper: ErrorHelper, private dialog: MatDialog, private router: Router, - private propertyTableHelperService: PropertyTableHelperService + private propertyTableHelperService: PropertyTableHelperService, + private parameterHelperService: ParameterHelperService ) {} loadControllerServices$ = createEffect(() => this.actions$.pipe( ofType(ControllerServicesActions.loadControllerServices), map((action) => action.request), - switchMap((request) => + concatLatestFrom(() => this.store.select(selectStatus)), + switchMap(([request, status]) => combineLatest([ this.controllerServiceService.getControllerServices(request.processGroupId), - this.controllerServiceService.getBreadcrumbs(request.processGroupId) + this.controllerServiceService.getFlow(request.processGroupId) ]).pipe( - map(([controllerServicesResponse, breadcrumbsResponse]) => + map(([controllerServicesResponse, flowResponse]) => ControllerServicesActions.loadControllerServicesSuccess({ response: { - processGroupId: breadcrumbsResponse.id, + processGroupId: flowResponse.processGroupFlow.id, controllerServices: controllerServicesResponse.controllerServices, loadedTimestamp: controllerServicesResponse.currentTime, - breadcrumb: breadcrumbsResponse + breadcrumb: flowResponse.processGroupFlow.breadcrumb, + parameterContext: flowResponse.processGroupFlow.parameterContext ?? null } }) ), - catchError((error) => - of( - ControllerServicesActions.controllerServicesApiError({ - error: error.error - }) - ) - ) + catchError((errorResponse: HttpErrorResponse) => { + if (status === 'success') { + if (this.errorHelper.showErrorInContext(errorResponse.status)) { + return of(ErrorActions.snackBarError({ error: errorResponse.error })); + } else { + return of(this.errorHelper.fullScreenError(errorResponse)); + } + } else { + return of(this.errorHelper.fullScreenError(errorResponse)); + } + }) ) ) ) @@ -149,13 +154,10 @@ export class ControllerServicesEffects { } }) ), - catchError((error) => - of( - ControllerServicesActions.controllerServicesApiError({ - error: error.error - }) - ) - ) + catchError((errorResponse: HttpErrorResponse) => { + this.dialog.closeAll(); + return of(ErrorActions.snackBarError({ error: errorResponse.error })); + }) ) ) ) @@ -191,7 +193,7 @@ export class ControllerServicesEffects { ofType(ControllerServicesActions.openConfigureControllerServiceDialog), map((action) => action.request), concatLatestFrom(() => [ - this.store.select(selectCurrentParameterContext), + this.store.select(selectParameterContext), this.store.select(selectCurrentProcessGroupId) ]), tap(([request, parameterContext, processGroupId]) => { @@ -242,17 +244,9 @@ export class ControllerServicesEffects { }; if (parameterContext != null) { - editDialogReference.componentInstance.getParameters = (sensitive: boolean) => { - return this.flowService.getParameterContext(parameterContext.id).pipe( - take(1), - map((response) => response.component.parameters), - map((parameterEntities) => { - return parameterEntities - .map((parameterEntity: ParameterEntity) => parameterEntity.parameter) - .filter((parameter: Parameter) => parameter.sensitive == sensitive); - }) - ); - }; + editDialogReference.componentInstance.getParameters = this.parameterHelperService.getParameters( + parameterContext.id + ); editDialogReference.componentInstance.parameterContext = parameterContext; editDialogReference.componentInstance.goToParameter = () => { @@ -260,74 +254,8 @@ export class ControllerServicesEffects { goTo(commands, 'Parameter'); }; - editDialogReference.componentInstance.convertToParameter = ( - name: string, - sensitive: boolean, - value: string | null - ) => { - return this.parameterService.getParameterContext(parameterContext.id, false).pipe( - switchMap((parameterContextEntity) => { - const existingParameters: string[] = - parameterContextEntity.component.parameters.map( - (parameterEntity: ParameterEntity) => parameterEntity.parameter.name - ); - const convertToParameterDialogRequest: EditParameterRequest = { - parameter: { - name, - value, - sensitive, - description: '' - }, - existingParameters - }; - const convertToParameterDialogReference = this.dialog.open(EditParameterDialog, { - data: convertToParameterDialogRequest, - panelClass: 'medium-dialog' - }); - - convertToParameterDialogReference.componentInstance.saving$ = - this.store.select(selectParameterSaving); - - convertToParameterDialogReference.componentInstance.cancel.pipe( - takeUntil(convertToParameterDialogReference.afterClosed()), - tap(() => ParameterActions.stopPollingParameterContextUpdateRequest()) - ); - - return convertToParameterDialogReference.componentInstance.editParameter.pipe( - takeUntil(convertToParameterDialogReference.afterClosed()), - switchMap((dialogResponse: EditParameterResponse) => { - this.store.dispatch( - ParameterActions.submitParameterContextUpdateRequest({ - request: { - id: parameterContext.id, - payload: { - revision: this.client.getRevision(parameterContextEntity), - component: { - id: parameterContextEntity.id, - parameters: [{ parameter: dialogResponse.parameter }] - } - } - } - }) - ); - - return this.store.select(selectParameterSaving).pipe( - takeUntil(convertToParameterDialogReference.afterClosed()), - filter((parameterSaving) => parameterSaving === false), - map(() => { - convertToParameterDialogReference.close(); - return `#{${dialogResponse.parameter.name}}`; - }) - ); - }) - ); - }), - catchError(() => { - // TODO handle error - return NEVER; - }) - ); - }; + editDialogReference.componentInstance.convertToParameter = + this.parameterHelperService.convertToParameter(parameterContext.id); } editDialogReference.componentInstance.goToService = (serviceId: string) => { @@ -341,8 +269,8 @@ export class ControllerServicesEffects { ]; goTo(commands, 'Controller Service'); }, - error: () => { - // TODO - handle error + error: (errorResponse: HttpErrorResponse) => { + this.store.dispatch(ErrorActions.snackBarError({ error: errorResponse.error })); } }); }; @@ -410,18 +338,31 @@ export class ControllerServicesEffects { } }) ), - catchError((error) => - of( - ControllerServicesActions.controllerServicesApiError({ - error: error.error - }) - ) - ) + catchError((errorResponse: HttpErrorResponse) => { + if (this.errorHelper.showErrorInContext(errorResponse.status)) { + return of( + ControllerServicesActions.controllerServicesBannerApiError({ + error: errorResponse.error + }) + ); + } else { + this.dialog.getDialogById(request.id)?.close('ROUTED'); + return of(this.errorHelper.fullScreenError(errorResponse)); + } + }) ) ) ) ); + controllerServicesBannerApiError$ = createEffect(() => + this.actions$.pipe( + ofType(ControllerServicesActions.controllerServicesBannerApiError), + map((action) => action.error), + switchMap((error) => of(ErrorActions.addBannerError({ error }))) + ) + ); + configureControllerServiceSuccess$ = createEffect( () => this.actions$.pipe( @@ -558,12 +499,8 @@ export class ControllerServicesEffects { } }) ), - catchError((error) => - of( - ControllerServicesActions.controllerServicesApiError({ - error: error.error - }) - ) + catchError((errorResponse: HttpErrorResponse) => + of(ErrorActions.snackBarError({ error: errorResponse.error })) ) ) ) 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/controller-services/controller-services.reducer.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.reducer.ts index 0497d9edf2..179511805a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.reducer.ts +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.reducer.ts @@ -19,7 +19,7 @@ import { createReducer, on } from '@ngrx/store'; import { configureControllerService, configureControllerServiceSuccess, - controllerServicesApiError, + controllerServicesBannerApiError, createControllerService, createControllerServiceSuccess, deleteControllerService, @@ -47,9 +47,9 @@ export const initialState: ControllerServicesState = { name: '' } }, + parameterContext: null, saving: false, loadedTimestamp: '', - error: null, status: 'pending' }; @@ -67,15 +67,13 @@ export const controllerServicesReducer = createReducer( processGroupId: response.processGroupId, controllerServices: response.controllerServices, breadcrumb: response.breadcrumb, + parameterContext: response.parameterContext, loadedTimestamp: response.loadedTimestamp, - error: null, status: 'success' as const })), - on(controllerServicesApiError, (state, { error }) => ({ + on(controllerServicesBannerApiError, (state) => ({ ...state, - saving: false, - error, - status: 'error' as const + saving: false })), on(createControllerService, configureControllerService, deleteControllerService, (state) => ({ ...state, 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/controller-services/controller-services.selectors.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.selectors.ts index c9da553c3c..e6827829b8 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.selectors.ts +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.selectors.ts @@ -31,11 +31,21 @@ export const selectSaving = createSelector( (state: ControllerServicesState) => state.saving ); +export const selectStatus = createSelector( + selectControllerServicesState, + (state: ControllerServicesState) => state.status +); + export const selectCurrentProcessGroupId = createSelector( selectControllerServicesState, (state: ControllerServicesState) => state.processGroupId ); +export const selectParameterContext = createSelector( + selectControllerServicesState, + (state: ControllerServicesState) => state.parameterContext +); + export const selectProcessGroupIdFromRoute = createSelector(selectCurrentRoute, (route) => { if (route) { // always select the process group from the route 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/controller-services/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/controller-services/index.ts index 81bd22e170..2362424bc1 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/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/controller-services/index.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { ControllerServiceEntity } from '../../../../state/shared'; +import { ControllerServiceEntity, ParameterContextReferenceEntity } from '../../../../state/shared'; import { BreadcrumbEntity } from '../shared'; export const controllerServicesFeatureKey = 'controllerServiceListing'; @@ -28,6 +28,7 @@ export interface LoadControllerServicesResponse { processGroupId: string; breadcrumb: BreadcrumbEntity; controllerServices: ControllerServiceEntity[]; + parameterContext: ParameterContextReferenceEntity | null; loadedTimestamp: string; } @@ -65,8 +66,8 @@ export interface ControllerServicesState { processGroupId: string; breadcrumb: BreadcrumbEntity; controllerServices: ControllerServiceEntity[]; + parameterContext: ParameterContextReferenceEntity | null; saving: boolean; loadedTimestamp: string; - error: string | null; - status: 'pending' | 'loading' | 'error' | 'success'; + status: 'pending' | 'loading' | 'success'; } 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 ef3bdc9b96..0fbd0a6289 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 @@ -19,7 +19,6 @@ import { Injectable } from '@angular/core'; import { FlowService } from '../../service/flow.service'; import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects'; import * as FlowActions from './flow.actions'; -import * as ParameterActions from '../parameter/parameter.actions'; import * as StatusHistoryActions from '../../../../state/status-history/status-history.actions'; import { asyncScheduler, @@ -30,7 +29,6 @@ import { interval, map, mergeMap, - NEVER, Observable, of, switchMap, @@ -65,13 +63,7 @@ import { ConnectionManager } from '../../service/manager/connection-manager.serv import { MatDialog } from '@angular/material/dialog'; import { CreatePort } from '../../ui/canvas/items/port/create-port/create-port.component'; import { EditPort } from '../../ui/canvas/items/port/edit-port/edit-port.component'; -import { - ComponentType, - EditParameterRequest, - EditParameterResponse, - Parameter, - ParameterEntity -} from '../../../../state/shared'; +import { ComponentType } from '../../../../state/shared'; import { Router } from '@angular/router'; import { Client } from '../../../../service/client.service'; import { CanvasUtils } from '../../service/canvas-utils.service'; @@ -87,13 +79,10 @@ import { EditConnectionComponent } from '../../ui/canvas/items/connection/edit-c import { OkDialog } from '../../../../ui/common/ok-dialog/ok-dialog.component'; import { GroupComponents } from '../../ui/canvas/items/process-group/group-components/group-components.component'; import { EditProcessGroup } from '../../ui/canvas/items/process-group/edit-process-group/edit-process-group.component'; -import { ExtensionTypesService } from '../../../../service/extension-types.service'; import { ControllerServiceService } from '../../service/controller-service.service'; import { YesNoDialog } from '../../../../ui/common/yes-no-dialog/yes-no-dialog.component'; -import { EditParameterDialog } from '../../../../ui/common/edit-parameter-dialog/edit-parameter-dialog.component'; -import { selectParameterSaving } from '../parameter/parameter.selectors'; -import { ParameterService } from '../../service/parameter.service'; import { PropertyTableHelperService } from '../../../../service/property-table-helper.service'; +import { ParameterHelperService } from '../../service/parameter-helper.service'; @Injectable() export class FlowEffects { @@ -101,9 +90,7 @@ export class FlowEffects { private actions$: Actions, private store: Store, private flowService: FlowService, - private extensionTypesService: ExtensionTypesService, private controllerServiceService: ControllerServiceService, - private parameterService: ParameterService, private client: Client, private canvasUtils: CanvasUtils, private canvasView: CanvasView, @@ -111,7 +98,8 @@ export class FlowEffects { private connectionManager: ConnectionManager, private router: Router, private dialog: MatDialog, - private propertyTableHelperService: PropertyTableHelperService + private propertyTableHelperService: PropertyTableHelperService, + private parameterHelperService: ParameterHelperService ) {} reloadFlow$ = createEffect(() => @@ -874,17 +862,9 @@ export class FlowEffects { }; if (parameterContext != null) { - editDialogReference.componentInstance.getParameters = (sensitive: boolean) => { - return this.flowService.getParameterContext(parameterContext.id).pipe( - take(1), - map((response) => response.component.parameters), - map((parameterEntities) => { - return parameterEntities - .map((parameterEntity: ParameterEntity) => parameterEntity.parameter) - .filter((parameter: Parameter) => parameter.sensitive == sensitive); - }) - ); - }; + editDialogReference.componentInstance.getParameters = this.parameterHelperService.getParameters( + parameterContext.id + ); editDialogReference.componentInstance.parameterContext = parameterContext; editDialogReference.componentInstance.goToParameter = () => { @@ -892,74 +872,8 @@ export class FlowEffects { goTo(commands, 'Parameter'); }; - editDialogReference.componentInstance.convertToParameter = ( - name: string, - sensitive: boolean, - value: string | null - ) => { - return this.parameterService.getParameterContext(parameterContext.id, false).pipe( - switchMap((parameterContextEntity) => { - const existingParameters: string[] = - parameterContextEntity.component.parameters.map( - (parameterEntity: ParameterEntity) => parameterEntity.parameter.name - ); - const convertToParameterDialogRequest: EditParameterRequest = { - parameter: { - name, - value, - sensitive, - description: '' - }, - existingParameters - }; - const convertToParameterDialogReference = this.dialog.open(EditParameterDialog, { - data: convertToParameterDialogRequest, - panelClass: 'medium-dialog' - }); - - convertToParameterDialogReference.componentInstance.saving$ = - this.store.select(selectParameterSaving); - - convertToParameterDialogReference.componentInstance.cancel.pipe( - takeUntil(convertToParameterDialogReference.afterClosed()), - tap(() => ParameterActions.stopPollingParameterContextUpdateRequest()) - ); - - return convertToParameterDialogReference.componentInstance.editParameter.pipe( - takeUntil(convertToParameterDialogReference.afterClosed()), - switchMap((dialogResponse: EditParameterResponse) => { - this.store.dispatch( - ParameterActions.submitParameterContextUpdateRequest({ - request: { - id: parameterContext.id, - payload: { - revision: this.client.getRevision(parameterContextEntity), - component: { - id: parameterContextEntity.id, - parameters: [{ parameter: dialogResponse.parameter }] - } - } - } - }) - ); - - return this.store.select(selectParameterSaving).pipe( - takeUntil(convertToParameterDialogReference.afterClosed()), - filter((parameterSaving) => parameterSaving === false), - map(() => { - convertToParameterDialogReference.close(); - return `#{${dialogResponse.parameter.name}}`; - }) - ); - }) - ); - }), - catchError(() => { - // TODO handle error - return NEVER; - }) - ); - }; + editDialogReference.componentInstance.convertToParameter = + this.parameterHelperService.convertToParameter(parameterContext.id); } editDialogReference.componentInstance.goToService = (serviceId: string) => { 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/parameter/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/parameter/index.ts index 215dbda6e7..c6eeb032b4 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/parameter/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/parameter/index.ts @@ -22,4 +22,5 @@ export const parameterFeatureKey = 'parameter'; export interface ParameterState { updateRequestEntity: ParameterContextUpdateRequestEntity | null; saving: boolean; + error: string | null; } 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/parameter/parameter.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/parameter/parameter.effects.ts index a58918c79a..e7f033594a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/parameter/parameter.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/parameter/parameter.effects.ts @@ -20,10 +20,11 @@ import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects'; import * as ParameterActions from './parameter.actions'; import { Store } from '@ngrx/store'; import { CanvasState } from '../index'; -import { asyncScheduler, catchError, from, interval, map, NEVER, of, switchMap, takeUntil, tap } from 'rxjs'; +import { asyncScheduler, catchError, from, interval, map, NEVER, of, switchMap, takeUntil } from 'rxjs'; import { ParameterContextUpdateRequest } from '../../../../state/shared'; import { selectUpdateRequest } from './parameter.selectors'; import { ParameterService } from '../../service/parameter.service'; +import { HttpErrorResponse } from '@angular/common/http'; @Injectable() export class ParameterEffects { @@ -46,12 +47,8 @@ export class ParameterEffects { } }) ), - catchError((error) => - of( - ParameterActions.parameterApiError({ - error: error.error - }) - ) + catchError((errorResponse: HttpErrorResponse) => + of(ParameterActions.parameterApiError({ error: errorResponse.error })) ) ) ) @@ -140,12 +137,22 @@ export class ParameterEffects { this.actions$.pipe( ofType(ParameterActions.deleteParameterContextUpdateRequest), concatLatestFrom(() => this.store.select(selectUpdateRequest)), - tap(([, updateRequest]) => { + switchMap(([, updateRequest]) => { if (updateRequest) { - this.parameterService.deleteParameterContextUpdate(updateRequest.request).subscribe(); + return from(this.parameterService.deleteParameterContextUpdate(updateRequest.request)).pipe( + map(() => ParameterActions.editParameterContextComplete()), + catchError((error) => + of( + ParameterActions.parameterApiError({ + error: error.error + }) + ) + ) + ); + } else { + return of(ParameterActions.editParameterContextComplete()); } - }), - switchMap(() => of(ParameterActions.editParameterContextComplete())) + }) ) ); } 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/parameter/parameter.reducer.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/parameter/parameter.reducer.ts index 8c2ad0055d..50e36b9810 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/parameter/parameter.reducer.ts +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/parameter/parameter.reducer.ts @@ -19,6 +19,7 @@ import { createReducer, on } from '@ngrx/store'; import { ParameterState } from './index'; import { editParameterContextComplete, + parameterApiError, pollParameterContextUpdateRequestSuccess, submitParameterContextUpdateRequest, submitParameterContextUpdateRequestSuccess @@ -26,7 +27,8 @@ import { export const initialState: ParameterState = { updateRequestEntity: null, - saving: false + saving: false, + error: null }; export const parameterReducer = createReducer( @@ -35,13 +37,15 @@ export const parameterReducer = createReducer( ...state, saving: true })), + on(parameterApiError, (state, { error }) => ({ + ...state, + error + })), on(submitParameterContextUpdateRequestSuccess, pollParameterContextUpdateRequestSuccess, (state, { response }) => ({ ...state, updateRequestEntity: response.requestEntity })), - on(editParameterContextComplete, (state) => ({ - ...state, - saving: false, - updateRequestEntity: null + on(editParameterContextComplete, () => ({ + ...initialState })) ); 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/controller-service/controller-services.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/controller-service/controller-services.component.html index 0b3b547be5..e63b10dc84 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.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/controller-service/controller-services.component.html @@ -35,14 +35,14 @@ -
+
{ - return of(ErrorActions.snackBarError({ error: errorResponse.error })); - }) + catchError((errorResponse: HttpErrorResponse) => + of(ErrorActions.snackBarError({ error: errorResponse.error })) + ) ) ) ) diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/controller-service-state.actions.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/controller-service-state.actions.ts index f2e74aebb6..865c7ef6e5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/controller-service-state.actions.ts +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/controller-service-state.actions.ts @@ -26,62 +26,62 @@ import { } from './index'; export const resetEnableControllerServiceState = createAction( - '[Enable Controller Service] Reset Enable Controller Service State' + '[Controller Service State] Reset Enable Controller Service State' ); export const setControllerService = createAction( - '[Enable Controller Service] Set Controller Service', + '[Controller Service State] Set Controller Service', props<{ request: SetControllerServiceRequest; }>() ); export const submitEnableRequest = createAction( - '[Enable Controller Service] Submit Enable Request', + '[Controller Service State] Submit Enable Request', props<{ request: SetEnableControllerServiceRequest; }>() ); -export const submitDisableRequest = createAction('[Enable Controller Service] Submit Disable Request'); +export const submitDisableRequest = createAction('[Controller Service State] Submit Disable Request'); -export const setEnableControllerService = createAction('[Enable Controller Service] Set Enable Controller Service'); +export const setEnableControllerService = createAction('[Controller Service State] Set Enable Controller Service'); export const setEnableControllerServiceSuccess = createAction( - '[Enable Controller Service] Set Enable Controller Service Success', + '[Controller Service State] Set Enable Controller Service Success', props<{ response: ControllerServiceStepResponse; }>() ); -export const updateReferencingServices = createAction('[Enable Controller Service] Update Referencing Services'); +export const updateReferencingServices = createAction('[Controller Service State] Update Referencing Services'); export const updateReferencingServicesSuccess = createAction( - '[Enable Controller Service] Update Referencing Services Success', + '[Controller Service State] Update Referencing Services Success', props<{ response: ReferencingComponentsStepResponse; }>() ); -export const updateReferencingComponents = createAction('[Enable Controller Service] Update Referencing Components'); +export const updateReferencingComponents = createAction('[Controller Service State] Update Referencing Components'); export const updateReferencingComponentsSuccess = createAction( - '[Enable Controller Service] Update Referencing Components Success', + '[Controller Service State] Update Referencing Components Success', props<{ response: ReferencingComponentsStepResponse; }>() ); export const startPollingControllerService = createAction( - '[Enable Controller Service] Start Polling Controller Service' + '[Controller Service State] Start Polling Controller Service' ); -export const stopPollingControllerService = createAction('[Enable Controller Service] Stop Polling Controller Service'); +export const stopPollingControllerService = createAction('[Controller Service State] Stop Polling Controller Service'); -export const pollControllerService = createAction('[Enable Controller Service] Poll Controller Service'); +export const pollControllerService = createAction('[Controller Service State] Poll Controller Service'); export const pollControllerServiceSuccess = createAction( - '[Enable Controller Service] Poll Controller Service Success', + '[Controller Service State] Poll Controller Service Success', props<{ response: ControllerServiceStepResponse; previousStep: SetEnableStep; @@ -89,25 +89,14 @@ export const pollControllerServiceSuccess = createAction( ); export const setEnableStepFailure = createAction( - '[Enable Controller Service] Set Enable Step Failure', + '[Controller Service State] Set Enable Step Failure', props<{ response: SetEnableStepFailure; }>() ); -export const controllerServiceApiError = createAction( - '[Enable Controller Service] Controller Service Api Error', - props<{ - error: string; - }>() -); - -export const clearControllerServiceApiError = createAction( - '[Enable Controller Service] Clear Controller Service Api Error' -); - export const showOkDialog = createAction( - '[Enable Controller Service] Show Ok Dialog', + '[Controller Service State] Show Ok Dialog', props<{ title: string; message: string; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/controller-service-state.effects.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/controller-service-state.effects.ts index 1010a4ed17..6a8c7a5ac5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/controller-service-state.effects.ts +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/controller-service-state.effects.ts @@ -87,42 +87,31 @@ export class ControllerServiceStateEffects { this.actions$.pipe( ofType(ControllerServiceActions.setEnableControllerService), concatLatestFrom(() => [ - this.store.select(selectControllerService), + this.store.select(selectControllerService).pipe(isDefinedAndNotNull()), this.store.select(selectControllerServiceSetEnableRequest) ]), - switchMap(([, controllerService, setEnableRequest]) => { - if (controllerService) { - return from( - this.controllerServiceStateService.setEnable(controllerService, setEnableRequest.enable) - ).pipe( - map((response) => - ControllerServiceActions.setEnableControllerServiceSuccess({ + switchMap(([, controllerService, setEnableRequest]) => + from(this.controllerServiceStateService.setEnable(controllerService, setEnableRequest.enable)).pipe( + map((response) => + ControllerServiceActions.setEnableControllerServiceSuccess({ + response: { + controllerService: response, + currentStep: setEnableRequest.currentStep + } + }) + ), + catchError((error) => + of( + ControllerServiceActions.setEnableStepFailure({ response: { - controllerService: response, - currentStep: setEnableRequest.currentStep + step: setEnableRequest.currentStep, + error: error.error } }) - ), - catchError((error) => - of( - ControllerServiceActions.setEnableStepFailure({ - response: { - step: setEnableRequest.currentStep, - error: error.error - } - }) - ) ) - ); - } else { - return of( - ControllerServiceActions.showOkDialog({ - title: 'Enable Service', - message: 'Controller Service not initialized' - }) - ); - } - }) + ) + ) + ) ) ); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/controller-service-state.reducer.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/controller-service-state.reducer.ts index 5166796a4d..77dd01c534 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/controller-service-state.reducer.ts +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/controller-service-state.reducer.ts @@ -18,8 +18,6 @@ import { createReducer, on } from '@ngrx/store'; import { ControllerServiceState, SetEnableStep } from './index'; import { - clearControllerServiceApiError, - controllerServiceApiError, setEnableStepFailure, pollControllerServiceSuccess, resetEnableControllerServiceState, @@ -39,7 +37,6 @@ export const initialState: ControllerServiceState = { scope: 'SERVICE_ONLY' }, controllerService: null, - error: null, status: 'pending' }; @@ -91,15 +88,5 @@ export const controllerServiceStateReducer = createReducer( error: response }, status: 'error' as const - })), - on(controllerServiceApiError, (state, { error }) => ({ - ...state, - error: error, - status: 'error' as const - })), - on(clearControllerServiceApiError, (state) => ({ - ...state, - error: null, - status: 'pending' as const })) ); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/index.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/index.ts index 32a0e88a42..a7566d4e53 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/index.ts +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/contoller-service-state/index.ts @@ -76,6 +76,5 @@ export interface SetEnableRequest { export interface ControllerServiceState { setEnableRequest: SetEnableRequest; controllerService: ControllerServiceEntity | null; - error: string | null; status: 'pending' | 'loading' | 'error' | 'success'; }