diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/feature/cluster.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/feature/cluster.component.html index 5e07e2ddb8..2a3996c099 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/feature/cluster.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/feature/cluster.component.html @@ -21,7 +21,7 @@

NiFi Cluster

- + @if (getTabLinks(); as tabs) {
diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/feature/cluster.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/feature/cluster.component.ts index 3e809ababc..575973cb1a 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/feature/cluster.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/feature/cluster.component.ts @@ -33,6 +33,7 @@ import { CurrentUser } from '../../../state/current-user'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { selectCurrentRoute } from '../../../state/router/router.selectors'; import { resetSystemDiagnostics } from '../../../state/system-diagnostics/system-diagnostics.actions'; +import { clearBannerErrors } from '../../../state/error/error.actions'; interface TabLink { label: string; @@ -82,6 +83,7 @@ export class Cluster implements OnInit, OnDestroy { ngOnDestroy(): void { this.store.dispatch(resetClusterState()); this.store.dispatch(resetSystemDiagnostics()); + this.store.dispatch(clearBannerErrors()); } refresh() { diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/feature/cluster.module.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/feature/cluster.module.ts index 35f1b0015f..e6926aa0fe 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/feature/cluster.module.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/feature/cluster.module.ts @@ -26,6 +26,7 @@ import { ClusterListingEffects } from '../state/cluster-listing/cluster-listing. import { ClusterRoutingModule } from './cluster-routing.module'; import { MatTabsModule } from '@angular/material/tabs'; import { MatIconButton } from '@angular/material/button'; +import { ErrorBanner } from '../../../ui/common/error-banner/error-banner.component'; @NgModule({ declarations: [Cluster], @@ -37,7 +38,8 @@ import { MatIconButton } from '@angular/material/button'; StoreModule.forFeature(clusterFeatureKey, reducers), EffectsModule.forFeature(ClusterListingEffects), MatTabsModule, - MatIconButton + MatIconButton, + ErrorBanner ] }) export class ClusterModule {} diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/state/cluster-listing/cluster-listing.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/state/cluster-listing/cluster-listing.effects.ts index 96bfa3231d..2173d714ff 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/state/cluster-listing/cluster-listing.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/cluster/state/cluster-listing/cluster-listing.effects.ts @@ -16,14 +16,13 @@ */ import { Injectable } from '@angular/core'; -import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; import { ActionCreator, Creator, Store } from '@ngrx/store'; import { NiFiState } from '../../../../state'; import { ErrorHelper } from '../../../../service/error-helper.service'; import { Router } from '@angular/router'; import * as ClusterListingActions from './cluster-listing.actions'; -import { catchError, from, map, of, switchMap, take, tap } from 'rxjs'; -import { SystemDiagnosticsService } from '../../../../service/system-diagnostics.service'; +import { catchError, filter, from, map, of, switchMap, take, tap } from 'rxjs'; import { HttpErrorResponse } from '@angular/common/http'; import { selectClusterListingStatus } from './cluster-listing.selectors'; import { reloadSystemDiagnostics } from '../../../../state/system-diagnostics/system-diagnostics.actions'; @@ -35,6 +34,7 @@ import { ClusterNodeDetailDialog } from '../../ui/cluster-node-listing/cluster-n import * as ErrorActions from '../../../../state/error/error.actions'; import { SelectClusterNodeRequest } from './index'; import { selectCurrentUser } from '../../../../state/current-user/current-user.selectors'; +import { concatLatestFrom } from '@ngrx/operators'; @Injectable() export class ClusterListingEffects { @@ -43,7 +43,6 @@ export class ClusterListingEffects { private store: Store, private errorHelper: ErrorHelper, private router: Router, - private systemDiagnosticsService: SystemDiagnosticsService, private clusterService: ClusterService, private dialog: MatDialog ) {} @@ -51,12 +50,6 @@ export class ClusterListingEffects { loadClusterListing$ = createEffect(() => this.actions$.pipe( ofType(ClusterListingActions.loadClusterListing), - concatLatestFrom(() => this.store.select(selectCurrentUser)), - tap(([, currentUser]) => { - if (currentUser.systemPermissions.canRead) { - this.store.dispatch(reloadSystemDiagnostics({ request: { nodewise: true } })); - } - }), concatLatestFrom(() => [this.store.select(selectClusterListingStatus)]), switchMap(([, listingStatus]) => from(this.clusterService.getClusterListing()).pipe( @@ -69,6 +62,22 @@ export class ClusterListingEffects { ) ); + loadClusterListingSuccess$ = createEffect(() => + this.actions$.pipe( + ofType(ClusterListingActions.loadClusterListingSuccess), + concatLatestFrom(() => this.store.select(selectCurrentUser)), + filter(([, currentUser]) => currentUser.systemPermissions.canRead), + map(() => + reloadSystemDiagnostics({ + request: { + nodewise: true, + errorStrategy: 'banner' + } + }) + ) + ) + ); + confirmAndDisconnectNode$ = createEffect( () => this.actions$.pipe( diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/cluster-summary.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/cluster-summary.actions.ts index 1d0e6ffcb6..2d99e96804 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/cluster-summary.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/cluster-summary.actions.ts @@ -41,13 +41,6 @@ export const setDisconnectionAcknowledged = createAction( props<{ disconnectionAcknowledged: boolean }>() ); -export const clusterSummaryApiError = createAction( - `${CLUSTER_SUMMARY_STATE_PREFIX} Cluster Summary Api Error`, - props<{ error: string }>() -); - -export const clearClusterSummaryApiError = createAction(`${CLUSTER_SUMMARY_STATE_PREFIX} Clear About Api Error`); - export const searchCluster = createAction( `${CLUSTER_SUMMARY_STATE_PREFIX} Search Cluster`, props<{ request: ClusterSearchRequest }>() diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/cluster-summary.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/cluster-summary.effects.ts index 7fe7949a32..00cf528a8a 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/cluster-summary.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/cluster-summary.effects.ts @@ -19,6 +19,7 @@ import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { concatLatestFrom } from '@ngrx/operators'; import * as ClusterSummaryActions from './cluster-summary.actions'; +import { acknowledgeClusterConnectionChange, setDisconnectionAcknowledged } from './cluster-summary.actions'; import { asyncScheduler, catchError, delay, filter, from, interval, map, of, switchMap, takeUntil, tap } from 'rxjs'; import { ClusterService } from '../../service/cluster.service'; import { selectClusterSummary } from './cluster-summary.selectors'; @@ -27,7 +28,6 @@ import { Store } from '@ngrx/store'; import { ClusterSummary, ClusterSummaryState } from './index'; import { HttpErrorResponse } from '@angular/common/http'; import * as ErrorActions from '../error/error.actions'; -import { acknowledgeClusterConnectionChange, setDisconnectionAcknowledged } from './cluster-summary.actions'; import { OkDialog } from '../../ui/common/ok-dialog/ok-dialog.component'; import { MEDIUM_DIALOG } from '../../index'; import { MatDialog } from '@angular/material/dialog'; @@ -66,7 +66,15 @@ export class ClusterSummaryEffects { response }); }), - catchError((error) => of(ClusterSummaryActions.clusterSummaryApiError({ error: error.error }))) + catchError((errorResponse: HttpErrorResponse) => + of( + ErrorActions.snackBarError({ + error: `Failed to load cluster summary - [${ + errorResponse.error || errorResponse.status + }]` + }) + ) + ) ) ); }) @@ -138,7 +146,13 @@ export class ClusterSummaryEffects { }) ), catchError((errorResponse: HttpErrorResponse) => - of(ErrorActions.snackBarError({ error: errorResponse.error })) + of( + ErrorActions.snackBarError({ + error: `Failed to search cluster summary - [${ + errorResponse.error || errorResponse.status + }]` + }) + ) ) ); }) diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/cluster-summary.reducer.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/cluster-summary.reducer.ts index 926ee842e8..3eb25a5e74 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/cluster-summary.reducer.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/cluster-summary.reducer.ts @@ -18,8 +18,6 @@ import { createReducer, on } from '@ngrx/store'; import { ClusterSummaryState } from './index'; import { - clearClusterSummaryApiError, - clusterSummaryApiError, loadClusterSummary, loadClusterSummarySuccess, searchClusterSuccess, @@ -30,7 +28,6 @@ export const initialState: ClusterSummaryState = { disconnectionAcknowledged: false, clusterSummary: null, searchResults: null, - error: null, status: 'pending' }; @@ -43,19 +40,8 @@ export const clusterSummaryReducer = createReducer( on(loadClusterSummarySuccess, (state, { response }) => ({ ...state, clusterSummary: response.clusterSummary, - error: null, status: 'success' as const })), - on(clusterSummaryApiError, (state, { error }) => ({ - ...state, - error, - status: 'error' as const - })), - on(clearClusterSummaryApiError, (state) => ({ - ...state, - error: null, - status: 'pending' as const - })), on(searchClusterSuccess, (state, { response }) => ({ ...state, searchResults: response diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/index.ts index 2d314c0eac..edf79d8d9e 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/cluster-summary/index.ts @@ -46,6 +46,5 @@ export interface ClusterSummaryState { disconnectionAcknowledged: boolean; clusterSummary: ClusterSummary | null; searchResults: ClusterSearchResults | null; - error: string | null; - status: 'pending' | 'loading' | 'error' | 'success'; + status: 'pending' | 'loading' | 'success'; } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/component-state.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/component-state.actions.ts index 08f81a72e3..8b9a7c7e1d 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/component-state.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/component-state.actions.ts @@ -32,11 +32,6 @@ export const loadComponentStateSuccess = createAction( export const openComponentStateDialog = createAction(`${COMPONENT_STATE_PREFIX} Open Component State Dialog`); -export const componentStateApiError = createAction( - `${COMPONENT_STATE_PREFIX} Component State API error`, - props<{ error: string }>() -); - export const clearComponentState = createAction(`${COMPONENT_STATE_PREFIX} Clear Component State`); export const reloadComponentState = createAction(`${COMPONENT_STATE_PREFIX} Reload Component State`); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/component-state.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/component-state.effects.ts index 7dda29edbd..fa1ebd0886 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/component-state.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/component-state.effects.ts @@ -21,14 +21,16 @@ import { concatLatestFrom } from '@ngrx/operators'; import { Store } from '@ngrx/store'; import { NiFiState } from '../index'; import * as ComponentStateActions from './component-state.actions'; +import { resetComponentState } from './component-state.actions'; import { catchError, from, map, of, switchMap, tap } from 'rxjs'; import { MatDialog } from '@angular/material/dialog'; import { ComponentStateService } from '../../service/component-state.service'; import { ComponentStateDialog } from '../../ui/common/component-state/component-state.component'; -import { resetComponentState } from './component-state.actions'; import { selectComponentUri } from './component-state.selectors'; import { isDefinedAndNotNull } from '../shared'; import { LARGE_DIALOG } from '../../index'; +import * as ErrorActions from '../error/error.actions'; +import { HttpErrorResponse } from '@angular/common/http'; @Injectable() export class ComponentStateEffects { @@ -53,10 +55,12 @@ export class ComponentStateEffects { } }) ), - catchError((error) => + catchError((errorResponse: HttpErrorResponse) => of( - ComponentStateActions.componentStateApiError({ - error: error.error + ErrorActions.snackBarError({ + error: `Failed to get the component state for ${request.componentName}. - [${ + errorResponse.error || errorResponse.status + }]` }) ) ) @@ -99,10 +103,12 @@ export class ComponentStateEffects { from( this.componentStateService.clearComponentState({ componentUri }).pipe( map(() => ComponentStateActions.reloadComponentState()), - catchError((error) => + catchError((errorResponse: HttpErrorResponse) => of( - ComponentStateActions.componentStateApiError({ - error: error.error + ErrorActions.addBannerError({ + error: `Failed to clear the component state. - [${ + errorResponse.error || errorResponse.status + }]` }) ) ) @@ -126,10 +132,12 @@ export class ComponentStateEffects { } }) ), - catchError((error) => + catchError((errorResponse: HttpErrorResponse) => of( - ComponentStateActions.componentStateApiError({ - error: error.error + ErrorActions.addBannerError({ + error: `Failed to reload the component state. - [${ + errorResponse.error || errorResponse.status + }]` }) ) ) diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/component-state.reducer.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/component-state.reducer.ts index 74cc7354e8..fda16fca46 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/component-state.reducer.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/component-state.reducer.ts @@ -18,11 +18,10 @@ import { ComponentStateState } from './index'; import { createReducer, on } from '@ngrx/store'; import { - resetComponentState, - loadComponentStateSuccess, - componentStateApiError, getComponentStateAndOpenDialog, - reloadComponentStateSuccess + loadComponentStateSuccess, + reloadComponentStateSuccess, + resetComponentState } from './component-state.actions'; export const initialState: ComponentStateState = { @@ -30,8 +29,7 @@ export const initialState: ComponentStateState = { componentUri: null, componentState: null, canClear: null, - status: 'pending', - error: null + status: 'pending' }; export const componentStateReducer = createReducer( @@ -45,15 +43,9 @@ export const componentStateReducer = createReducer( })), on(loadComponentStateSuccess, reloadComponentStateSuccess, (state, { response }) => ({ ...state, - error: null, status: 'success' as const, componentState: response.componentState })), - on(componentStateApiError, (state, { error }) => ({ - ...state, - error, - status: 'error' as const - })), on(resetComponentState, () => ({ ...initialState })) diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/index.ts index 86047add7a..64abe2f1b1 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/component-state/index.ts @@ -66,6 +66,5 @@ export interface ComponentStateState { componentUri: string | null; componentState: ComponentState | null; canClear: boolean | null; - error: string | null; - status: 'pending' | 'loading' | 'error' | 'success'; + status: 'pending' | 'loading' | 'success'; } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/current-user.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/current-user.actions.ts index b71f93ae97..8add0796ee 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/current-user.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/current-user.actions.ts @@ -25,10 +25,6 @@ export const loadCurrentUserSuccess = createAction( props<{ response: LoadCurrentUserResponse }>() ); -export const currentUserApiError = createAction('[Current User] Current User Api Error', props<{ error: string }>()); - -export const clearCurrentUserApiError = createAction('[Current User] Clear Current User Api Error'); - export const startCurrentUserPolling = createAction('[Current User] Start Current User Polling'); export const stopCurrentUserPolling = createAction('[Current User] Stop Current User Polling'); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/current-user.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/current-user.effects.ts index 038d63fa9d..f24379ff24 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/current-user.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/current-user.effects.ts @@ -20,12 +20,14 @@ import { Actions, createEffect, ofType } from '@ngrx/effects'; import * as UserActions from './current-user.actions'; import { asyncScheduler, catchError, from, interval, map, of, switchMap, takeUntil } from 'rxjs'; import { CurrentUserService } from '../../service/current-user.service'; +import { ErrorHelper } from '../../service/error-helper.service'; @Injectable() export class CurrentUserEffects { constructor( private actions$: Actions, - private userService: CurrentUserService + private userService: CurrentUserService, + private errorHelper: ErrorHelper ) {} loadCurrentUser$ = createEffect(() => @@ -41,7 +43,7 @@ export class CurrentUserEffects { } }) ), - catchError((error) => of(UserActions.currentUserApiError({ error: error.error }))) + catchError((error) => of(this.errorHelper.fullScreenError(error))) ) ); }) diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/current-user.reducer.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/current-user.reducer.ts index ed47a48d0f..a2fe0d4267 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/current-user.reducer.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/current-user.reducer.ts @@ -18,12 +18,7 @@ import { createReducer, on } from '@ngrx/store'; import { CurrentUserState } from './index'; import { Permissions } from '../shared'; -import { - clearCurrentUserApiError, - loadCurrentUser, - loadCurrentUserSuccess, - currentUserApiError -} from './current-user.actions'; +import { loadCurrentUser, loadCurrentUserSuccess } from './current-user.actions'; export const NO_PERMISSIONS: Permissions = { canRead: false, @@ -45,7 +40,6 @@ export const initialState: CurrentUserState = { tenantsPermissions: NO_PERMISSIONS, componentRestrictionPermissions: [] }, - error: null, status: 'pending' }; @@ -58,17 +52,6 @@ export const currentUserReducer = createReducer( on(loadCurrentUserSuccess, (state, { response }) => ({ ...state, user: response.user, - error: null, status: 'success' as const - })), - on(currentUserApiError, (state, { error }) => ({ - ...state, - error: error, - status: 'error' as const - })), - on(clearCurrentUserApiError, (state) => ({ - ...state, - error: null, - status: 'pending' as const })) ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/index.ts index ecdd9520bd..1b9b0e3d07 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/current-user/index.ts @@ -45,6 +45,5 @@ export interface CurrentUser { export interface CurrentUserState { user: CurrentUser; - error: string | null; - status: 'pending' | 'loading' | 'error' | 'success'; + status: 'pending' | 'loading' | 'success'; } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.actions.ts index 41b534e061..9d948febec 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.actions.ts @@ -21,6 +21,7 @@ import { LoadExtensionTypesForPoliciesResponse, LoadExtensionTypesForSettingsResponse } from './index'; +import { HttpErrorResponse } from '@angular/common/http'; export const loadExtensionTypesForCanvas = createAction('[Extension Types] Load Extension Types For Canvas'); @@ -45,7 +46,5 @@ export const loadExtensionTypesForPoliciesSuccess = createAction( export const extensionTypesApiError = createAction( '[Extension Types] Extension Types Api Error', - props<{ error: string }>() + props<{ error: HttpErrorResponse }>() ); - -export const clearExtensionTypesApiError = createAction('[Extension Types] Clear Extension Types Api Error'); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.effects.ts index cac209f3b2..3622c1fb2e 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.effects.ts @@ -20,6 +20,8 @@ import { Actions, createEffect, ofType } from '@ngrx/effects'; import * as ExtensionTypesActions from './extension-types.actions'; import { catchError, combineLatest, map, of, switchMap } from 'rxjs'; import { ExtensionTypesService } from '../../service/extension-types.service'; +import * as ErrorActions from '../error/error.actions'; +import { HttpErrorResponse } from '@angular/common/http'; @Injectable() export class ExtensionTypesEffects { @@ -46,7 +48,7 @@ export class ExtensionTypesEffects { } }) ), - catchError((error) => of(ExtensionTypesActions.extensionTypesApiError({ error: error.error }))) + catchError((error) => of(ExtensionTypesActions.extensionTypesApiError({ error }))) ) ) ) @@ -81,7 +83,7 @@ export class ExtensionTypesEffects { } }) ), - catchError((error) => of(ExtensionTypesActions.extensionTypesApiError({ error: error.error }))) + catchError((error) => of(ExtensionTypesActions.extensionTypesApiError({ error }))) ) ) ) @@ -116,7 +118,25 @@ export class ExtensionTypesEffects { } }) ), - catchError((error) => of(ExtensionTypesActions.extensionTypesApiError({ error: error.error }))) + catchError((errorResponse: HttpErrorResponse) => + of(ExtensionTypesActions.extensionTypesApiError({ error: errorResponse.error })) + ) + ) + ) + ) + ); + + extensionTypesApiError$ = createEffect(() => + this.actions$.pipe( + ofType(ExtensionTypesActions.extensionTypesApiError), + map((action) => action.error), + switchMap((errorResponse: HttpErrorResponse) => + of( + ErrorActions.snackBarError({ + error: `Failed to load extension types. You may not be able to create new Processors, Controller Services, Reporting Tasks, Parameter Providers, or Flow Analysis Rules. - [${ + errorResponse.error || errorResponse.status + }]` + }) ) ) ) diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.reducer.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.reducer.ts index 4ba7925049..1b30b34202 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.reducer.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.reducer.ts @@ -18,8 +18,6 @@ import { createReducer, on } from '@ngrx/store'; import { ExtensionTypesState } from './index'; import { - clearExtensionTypesApiError, - extensionTypesApiError, loadExtensionTypesForCanvas, loadExtensionTypesForCanvasSuccess, loadExtensionTypesForPoliciesSuccess, @@ -34,7 +32,6 @@ export const initialState: ExtensionTypesState = { registryClientTypes: [], flowAnalysisRuleTypes: [], parameterProviderTypes: [], - error: null, status: 'pending' }; @@ -49,7 +46,6 @@ export const extensionTypesReducer = createReducer( processorTypes: response.processorTypes, controllerServiceTypes: response.controllerServiceTypes, prioritizerTypes: response.prioritizers, - error: null, status: 'success' as const })), on(loadExtensionTypesForSettingsSuccess, (state, { response }) => ({ @@ -59,7 +55,6 @@ export const extensionTypesReducer = createReducer( registryClientTypes: response.registryClientTypes, parameterProviderTypes: response.parameterProviderTypes, flowAnalysisRuleTypes: response.flowAnalysisRuleTypes, - error: null, status: 'success' as const })), on(loadExtensionTypesForPoliciesSuccess, (state, { response }) => ({ @@ -69,17 +64,6 @@ export const extensionTypesReducer = createReducer( reportingTaskTypes: response.reportingTaskTypes, parameterProviderTypes: response.parameterProviderTypes, flowAnalysisRuleTypes: response.flowAnalysisRuleTypes, - error: null, status: 'success' as const - })), - on(extensionTypesApiError, (state, { error }) => ({ - ...state, - error: error, - status: 'error' as const - })), - on(clearExtensionTypesApiError, (state) => ({ - ...state, - error: null, - status: 'pending' as const })) ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/index.ts index f4b087da10..33fa4b4455 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/index.ts @@ -49,6 +49,5 @@ export interface ExtensionTypesState { registryClientTypes: DocumentedType[]; flowAnalysisRuleTypes: DocumentedType[]; parameterProviderTypes: DocumentedType[]; - error: string | null; - status: 'pending' | 'loading' | 'error' | 'success'; + status: 'pending' | 'loading' | 'success'; } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/flow-configuration.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/flow-configuration.actions.ts index bc47b8d804..c72808d709 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/flow-configuration.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/flow-configuration.actions.ts @@ -24,10 +24,3 @@ export const loadFlowConfigurationSuccess = createAction( '[Flow Configuration] Load Flow Configuration Success', props<{ response: LoadFlowConfigurationResponse }>() ); - -export const flowConfigurationApiError = createAction( - '[Flow Configuration] Flow Configuration Api Error', - props<{ error: string }>() -); - -export const flowConfigurationAboutApiError = createAction('[Flow Configuration] Clear Flow Configuration Api Error'); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/flow-configuration.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/flow-configuration.effects.ts index abee4aabdf..8d48654c51 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/flow-configuration.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/flow-configuration.effects.ts @@ -20,6 +20,8 @@ import { Actions, createEffect, ofType } from '@ngrx/effects'; import * as FlowConfigurationActions from './flow-configuration.actions'; import { catchError, from, map, of, switchMap } from 'rxjs'; import { FlowConfigurationService } from '../../service/flow-configuration.service'; +import * as ErrorActions from '../error/error.actions'; +import { HttpErrorResponse } from '@angular/common/http'; @Injectable() export class FlowConfigurationEffects { @@ -39,8 +41,14 @@ export class FlowConfigurationEffects { response }) ), - catchError((error) => - of(FlowConfigurationActions.flowConfigurationApiError({ error: error.error })) + catchError((errorResponse: HttpErrorResponse) => + of( + ErrorActions.snackBarError({ + error: `Failed to load Flow Configuration. - [${ + errorResponse.error || errorResponse.status + }]` + }) + ) ) ) ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/flow-configuration.reducer.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/flow-configuration.reducer.ts index 69c29c0271..74b1307361 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/flow-configuration.reducer.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/flow-configuration.reducer.ts @@ -17,16 +17,10 @@ import { createReducer, on } from '@ngrx/store'; import { FlowConfigurationState } from './index'; -import { - flowConfigurationApiError, - flowConfigurationAboutApiError, - loadFlowConfiguration, - loadFlowConfigurationSuccess -} from './flow-configuration.actions'; +import { loadFlowConfiguration, loadFlowConfigurationSuccess } from './flow-configuration.actions'; export const initialState: FlowConfigurationState = { flowConfiguration: null, - error: null, status: 'pending' }; @@ -39,17 +33,6 @@ export const flowConfigurationReducer = createReducer( on(loadFlowConfigurationSuccess, (state, { response }) => ({ ...state, flowConfiguration: response.flowConfiguration, - error: null, status: 'success' as const - })), - on(flowConfigurationApiError, (state, { error }) => ({ - ...state, - error: error, - status: 'error' as const - })), - on(flowConfigurationAboutApiError, (state) => ({ - ...state, - error: null, - status: 'pending' as const })) ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/index.ts index fc3750f80a..2a8cd011d5 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/flow-configuration/index.ts @@ -34,6 +34,5 @@ export interface FlowConfiguration { export interface FlowConfigurationState { flowConfiguration: FlowConfiguration | null; - error: string | null; - status: 'pending' | 'loading' | 'error' | 'success'; + status: 'pending' | 'loading' | 'success'; } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/index.ts index 81a5fd766e..6b44b7d4f1 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/index.ts @@ -75,6 +75,5 @@ export interface StatusHistoryResponse { export interface StatusHistoryState { statusHistory: StatusHistoryEntity; loadedTimestamp: string; - error: string | null; status: 'pending' | 'loading' | 'error' | 'success'; } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/status-history.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/status-history.actions.ts index 009ca842d5..c600549a39 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/status-history.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/status-history.actions.ts @@ -50,8 +50,8 @@ export const openStatusHistoryDialog = createAction( props<{ request: StatusHistoryRequest | NodeStatusHistoryRequest }>() ); -export const statusHistoryApiError = createAction( - `${STATUS_HISTORY_PREFIX} Load Status History error`, +export const statusHistoryBannerError = createAction( + `${STATUS_HISTORY_PREFIX} Status History Banner Error`, props<{ error: string }>() ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/status-history.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/status-history.effects.ts index 6a8469e0b9..22b0018bd3 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/status-history.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/status-history.effects.ts @@ -25,6 +25,9 @@ import { StatusHistoryRequest } from './index'; import { catchError, filter, from, map, of, switchMap, tap } from 'rxjs'; import { MatDialog } from '@angular/material/dialog'; import { StatusHistory } from '../../ui/common/status-history/status-history.component'; +import * as ErrorActions from '../../state/error/error.actions'; +import { HttpErrorResponse } from '@angular/common/http'; +import { ErrorHelper } from '../../service/error-helper.service'; @Injectable() export class StatusHistoryEffects { @@ -32,7 +35,8 @@ export class StatusHistoryEffects { private actions$: Actions, private store: Store, private statusHistoryService: StatusHistoryService, - private dialog: MatDialog + private dialog: MatDialog, + private errorHelper: ErrorHelper ) {} reloadComponentStatusHistory$ = createEffect(() => @@ -55,12 +59,8 @@ export class StatusHistoryEffects { } }) ), - catchError((error) => - of( - StatusHistoryActions.statusHistoryApiError({ - error: error.error - }) - ) + catchError((errorResponse: HttpErrorResponse) => + this.bannerOrFullScreenError(errorResponse) ) ) ) @@ -86,13 +86,7 @@ export class StatusHistoryEffects { } }) ), - catchError((error) => - of( - StatusHistoryActions.statusHistoryApiError({ - error: error.error - }) - ) - ) + catchError((errorResponse: HttpErrorResponse) => this.bannerOrFullScreenError(errorResponse)) ) ) ) @@ -119,12 +113,8 @@ export class StatusHistoryEffects { } }) ), - catchError((error) => - of( - StatusHistoryActions.statusHistoryApiError({ - error: error.error - }) - ) + catchError((errorResponse: HttpErrorResponse) => + this.snackBarOrFullScreenError(errorResponse) ) ) ) @@ -150,13 +140,7 @@ export class StatusHistoryEffects { } }) ), - catchError((error) => - of( - StatusHistoryActions.statusHistoryApiError({ - error: error.error - }) - ) - ) + catchError((errorResponse: HttpErrorResponse) => this.snackBarOrFullScreenError(errorResponse)) ) ) ) @@ -210,4 +194,30 @@ export class StatusHistoryEffects { ), { dispatch: false } ); + + statusHistoryBannerError$ = createEffect(() => + this.actions$.pipe( + ofType(StatusHistoryActions.statusHistoryBannerError), + map((action) => action.error), + switchMap((error) => of(ErrorActions.addBannerError({ error }))) + ) + ); + + private bannerOrFullScreenError(errorResponse: HttpErrorResponse) { + if (this.errorHelper.showErrorInContext(errorResponse.status)) { + const error = `Failed to reload Status History. - [${errorResponse.error || errorResponse.status}]`; + return of(StatusHistoryActions.statusHistoryBannerError({ error })); + } else { + return of(ErrorActions.fullScreenError(errorResponse.error)); + } + } + + private snackBarOrFullScreenError(errorResponse: HttpErrorResponse) { + if (this.errorHelper.showErrorInContext(errorResponse.status)) { + const error = `Failed to load Status History. - [${errorResponse.error || errorResponse.status}]`; + return of(ErrorActions.snackBarError({ error })); + } else { + return of(ErrorActions.fullScreenError(errorResponse.error)); + } + } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/status-history.reducer.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/status-history.reducer.ts index 6c2170d70d..cb937312a5 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/status-history.reducer.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/status-history/status-history.reducer.ts @@ -19,18 +19,18 @@ import { StatusHistoryEntity, StatusHistoryState } from './index'; import { createReducer, on } from '@ngrx/store'; import { clearStatusHistory, - reloadStatusHistory, + getStatusHistoryAndOpenDialog, loadStatusHistorySuccess, - statusHistoryApiError, - viewStatusHistoryComplete, + reloadStatusHistory, reloadStatusHistorySuccess, - getStatusHistoryAndOpenDialog + statusHistoryBannerError, + viewNodeStatusHistoryComplete, + viewStatusHistoryComplete } from './status-history.actions'; export const initialState: StatusHistoryState = { statusHistory: {} as StatusHistoryEntity, status: 'pending', - error: null, loadedTimestamp: '' }; @@ -44,15 +44,13 @@ export const statusHistoryReducer = createReducer( on(loadStatusHistorySuccess, reloadStatusHistorySuccess, (state, { response }) => ({ ...state, - error: null, status: 'success' as const, loadedTimestamp: response.statusHistory.statusHistory.generated, statusHistory: response.statusHistory })), - on(statusHistoryApiError, (state, { error }) => ({ + on(statusHistoryBannerError, (state) => ({ ...state, - error, status: 'error' as const })), @@ -60,7 +58,7 @@ export const statusHistoryReducer = createReducer( ...initialState })), - on(viewStatusHistoryComplete, () => ({ + on(viewStatusHistoryComplete, viewNodeStatusHistoryComplete, () => ({ ...initialState })) ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/index.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/index.ts index dcc03c47c8..b2c9e5521b 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/index.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/index.ts @@ -91,6 +91,7 @@ export interface SystemDiagnosticSnapshot { export interface SystemDiagnosticsRequest { nodewise: boolean; + errorStrategy?: 'banner' | 'snackbar'; } export interface SystemDiagnosticsResponse { @@ -100,7 +101,6 @@ export interface SystemDiagnosticsResponse { export interface SystemDiagnosticsState { systemDiagnostics: SystemDiagnostics | null; loadedTimestamp: string; - error: string | null; status: 'pending' | 'loading' | 'error' | 'success'; } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.actions.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.actions.ts index 52039b40a3..e09dc3be10 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.actions.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.actions.ts @@ -42,8 +42,13 @@ export const getSystemDiagnosticsAndOpenDialog = createAction( export const openSystemDiagnosticsDialog = createAction(`${SYSTEM_DIAGNOSTICS_PREFIX} Open System Diagnostics Dialog`); -export const systemDiagnosticsApiError = createAction( - `${SYSTEM_DIAGNOSTICS_PREFIX} Load System Diagnostics Error`, +export const systemDiagnosticsSnackbarError = createAction( + `${SYSTEM_DIAGNOSTICS_PREFIX} Load System Diagnostics Snackbar Error`, + props<{ error: string }>() +); + +export const systemDiagnosticsBannerError = createAction( + `${SYSTEM_DIAGNOSTICS_PREFIX} Load System Diagnostics Banner Error`, props<{ error: string }>() ); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.effects.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.effects.ts index 14aa0190b4..77fe2efb7c 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.effects.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.effects.ts @@ -26,6 +26,8 @@ import { catchError, from, map, of, switchMap, tap } from 'rxjs'; import { SystemDiagnosticsRequest } from './index'; import { SystemDiagnosticsDialog } from '../../ui/common/system-diagnostics-dialog/system-diagnostics-dialog.component'; import { LARGE_DIALOG } from '../../index'; +import * as ErrorActions from '../error/error.actions'; +import { HttpErrorResponse } from '@angular/common/http'; @Injectable() export class SystemDiagnosticsEffects { @@ -49,13 +51,24 @@ export class SystemDiagnosticsEffects { } }) ), - catchError((error) => - of( - SystemDiagnosticsActions.systemDiagnosticsApiError({ - error: error.error + catchError((errorResponse: HttpErrorResponse) => { + if (request.errorStrategy === 'snackbar') { + return of( + SystemDiagnosticsActions.systemDiagnosticsSnackbarError({ + error: `Failed to reload System Diagnostics. - [${ + errorResponse.error || errorResponse.status + }]` + }) + ); + } + return of( + SystemDiagnosticsActions.systemDiagnosticsBannerError({ + error: `Failed to reload System Diagnostics. - [${ + errorResponse.error || errorResponse.status + }]` }) - ) - ) + ); + }) ) ) ) @@ -74,10 +87,12 @@ export class SystemDiagnosticsEffects { } }) ), - catchError((error) => + catchError((errorResponse: HttpErrorResponse) => of( - SystemDiagnosticsActions.systemDiagnosticsApiError({ - error: error.error + SystemDiagnosticsActions.systemDiagnosticsSnackbarError({ + error: `Failed to load System Diagnostics. - [${ + errorResponse.error || errorResponse.status + }]` }) ) ) @@ -110,4 +125,20 @@ export class SystemDiagnosticsEffects { ), { dispatch: false } ); + + systemDiagnosticsBannerError$ = createEffect(() => + this.actions$.pipe( + ofType(SystemDiagnosticsActions.systemDiagnosticsBannerError), + map((action) => action.error), + switchMap((error) => of(ErrorActions.addBannerError({ error }))) + ) + ); + + systemDiagnosticsSnackbarError$ = createEffect(() => + this.actions$.pipe( + ofType(SystemDiagnosticsActions.systemDiagnosticsSnackbarError), + map((action) => action.error), + switchMap((error) => of(ErrorActions.snackBarError({ error }))) + ) + ); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.reducer.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.reducer.ts index 569167c24c..c4661c939f 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.reducer.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.reducer.ts @@ -18,19 +18,19 @@ import { SystemDiagnosticsState } from './index'; import { createReducer, on } from '@ngrx/store'; import { - reloadSystemDiagnostics, - loadSystemDiagnosticsSuccess, - resetSystemDiagnostics, - systemDiagnosticsApiError, - viewSystemDiagnosticsComplete, getSystemDiagnosticsAndOpenDialog, - reloadSystemDiagnosticsSuccess + loadSystemDiagnosticsSuccess, + reloadSystemDiagnostics, + reloadSystemDiagnosticsSuccess, + resetSystemDiagnostics, + systemDiagnosticsBannerError, + systemDiagnosticsSnackbarError, + viewSystemDiagnosticsComplete } from './system-diagnostics.actions'; export const initialSystemDiagnosticsState: SystemDiagnosticsState = { systemDiagnostics: null, status: 'pending', - error: null, loadedTimestamp: '' }; @@ -44,15 +44,13 @@ export const systemDiagnosticsReducer = createReducer( on(loadSystemDiagnosticsSuccess, reloadSystemDiagnosticsSuccess, (state, { response }) => ({ ...state, - error: null, status: 'success' as const, loadedTimestamp: response.systemDiagnostics.aggregateSnapshot.statsLastRefreshed, systemDiagnostics: response.systemDiagnostics })), - on(systemDiagnosticsApiError, (state, { error }) => ({ + on(systemDiagnosticsBannerError, systemDiagnosticsSnackbarError, (state) => ({ ...state, - error, status: 'error' as const })), diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.selectors.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.selectors.ts index a5f36804a3..de6adfbf81 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.selectors.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/system-diagnostics/system-diagnostics.selectors.ts @@ -30,11 +30,6 @@ export const selectSystemDiagnosticsLoadedTimestamp = createSelector( (state: SystemDiagnosticsState) => state.loadedTimestamp ); -export const selectSystemDiagnosticsError = createSelector( - selectSystemDiagnosticsState, - (state: SystemDiagnosticsState) => state.error -); - export const selectSystemDiagnosticsStatus = createSelector( selectSystemDiagnosticsState, (state: SystemDiagnosticsState) => state.status diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/component-state/component-state.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/component-state/component-state.component.html index f091aac161..ae93c442d3 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/component-state/component-state.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/component-state/component-state.component.html @@ -17,6 +17,7 @@

Component State

+
@if (componentName$ | async; as componentName) { diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/component-state/component-state.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/component-state/component-state.component.ts index e28e72bd01..ac88641cb4 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/component-state/component-state.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/component-state/component-state.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { AfterViewInit, Component, DestroyRef, inject, Input } from '@angular/core'; +import { AfterViewInit, Component, DestroyRef, inject, Input, OnDestroy } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatDialogModule } from '@angular/material/dialog'; import { MatTableDataSource, MatTableModule } from '@angular/material/table'; @@ -39,6 +39,8 @@ import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { selectClusterSummary } from '../../../state/cluster-summary/cluster-summary.selectors'; +import { ErrorBanner } from '../error-banner/error-banner.component'; +import { clearBannerErrors } from '../../../state/error/error.actions'; @Component({ selector: 'component-state', @@ -54,11 +56,12 @@ import { selectClusterSummary } from '../../../state/cluster-summary/cluster-sum AsyncPipe, ReactiveFormsModule, MatFormFieldModule, - MatInputModule + MatInputModule, + ErrorBanner ], styleUrls: ['./component-state.component.scss'] }) -export class ComponentStateDialog implements AfterViewInit { +export class ComponentStateDialog implements AfterViewInit, OnDestroy { @Input() initialSortColumn: 'key' | 'value' = 'key'; @Input() initialSortDirection: 'asc' | 'desc' = 'asc'; @@ -140,6 +143,10 @@ export class ComponentStateDialog implements AfterViewInit { }); } + ngOnDestroy(): void { + this.store.dispatch(clearBannerErrors()); + } + processStateMap(stateMap: StateMap, clusterState: boolean): StateItem[] { const stateEntries: StateEntry[] = stateMap.state ? stateMap.state : []; diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/status-history/status-history.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/status-history/status-history.component.html index b49aa25978..e86b03d2da 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/status-history/status-history.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/status-history/status-history.component.html @@ -17,6 +17,7 @@
@if (statusHistoryState$ | async; as statusHistoryState) {

Status History

+
diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/status-history/status-history.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/status-history/status-history.component.ts index b691b06ad5..12b0c01537 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/status-history/status-history.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/status-history/status-history.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { AfterViewInit, Component, DestroyRef, inject, Inject, OnInit } from '@angular/core'; +import { AfterViewInit, Component, DestroyRef, inject, Inject, OnDestroy, OnInit } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; import { StatusHistoryService } from '../../../service/status-history.service'; import { AsyncPipe, NgStyle } from '@angular/common'; @@ -51,6 +51,8 @@ import { Resizable } from '../resizable/resizable.component'; import { Instance, NIFI_NODE_CONFIG, Stats } from './index'; import { StatusHistoryChart } from './status-history-chart/status-history-chart.component'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { ErrorBanner } from '../error-banner/error-banner.component'; +import { clearBannerErrors } from '../../../state/error/error.actions'; @Component({ selector: 'status-history', @@ -68,11 +70,12 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; MatCheckboxModule, Resizable, StatusHistoryChart, - NgStyle + NgStyle, + ErrorBanner ], styleUrls: ['./status-history.component.scss'] }) -export class StatusHistory implements OnInit, AfterViewInit { +export class StatusHistory implements OnInit, OnDestroy, AfterViewInit { request: StatusHistoryRequest; statusHistoryState$ = this.store.select(selectStatusHistoryState); componentDetails$ = this.store.select(selectStatusHistoryComponentDetails); @@ -197,6 +200,10 @@ export class StatusHistory implements OnInit, AfterViewInit { }); } + ngOnDestroy(): void { + this.store.dispatch(clearBannerErrors()); + } + ngAfterViewInit(): void { // when the selected descriptor changes, update the chart this.statusHistoryForm diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/system-diagnostics-dialog/system-diagnostics-dialog.component.html b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/system-diagnostics-dialog/system-diagnostics-dialog.component.html index 85c648aef4..d6abd220c3 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/system-diagnostics-dialog/system-diagnostics-dialog.component.html +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/system-diagnostics-dialog/system-diagnostics-dialog.component.html @@ -17,6 +17,7 @@ @if ((systemDiagnostics$ | async)?.aggregateSnapshot; as systemDiagnostics) {

System Diagnostics

+
diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/system-diagnostics-dialog/system-diagnostics-dialog.component.ts b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/system-diagnostics-dialog/system-diagnostics-dialog.component.ts index a10f9f4c90..b07002c0c7 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/system-diagnostics-dialog/system-diagnostics-dialog.component.ts +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/system-diagnostics-dialog/system-diagnostics-dialog.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { MatTabsModule } from '@angular/material/tabs'; import { MatDialogModule } from '@angular/material/dialog'; @@ -33,6 +33,8 @@ import { TextTip } from '../tooltips/text-tip/text-tip.component'; import { NifiTooltipDirective } from '../tooltips/nifi-tooltip.directive'; import { isDefinedAndNotNull } from '../../../state/shared'; import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { ErrorBanner } from '../error-banner/error-banner.component'; +import { clearBannerErrors } from '../../../state/error/error.actions'; @Component({ selector: 'system-diagnostics-dialog', @@ -43,12 +45,13 @@ import { MatProgressBarModule } from '@angular/material/progress-bar'; MatDialogModule, MatButtonModule, NifiTooltipDirective, - MatProgressBarModule + MatProgressBarModule, + ErrorBanner ], templateUrl: './system-diagnostics-dialog.component.html', styleUrls: ['./system-diagnostics-dialog.component.scss'] }) -export class SystemDiagnosticsDialog implements OnInit { +export class SystemDiagnosticsDialog implements OnInit, OnDestroy { systemDiagnostics$ = this.store.select(selectSystemDiagnostics); loadedTimestamp$ = this.store.select(selectSystemDiagnosticsLoadedTimestamp); status$ = this.store.select(selectSystemDiagnosticsStatus); @@ -69,11 +72,16 @@ export class SystemDiagnosticsDialog implements OnInit { }); } + ngOnDestroy(): void { + this.store.dispatch(clearBannerErrors()); + } + refreshSystemDiagnostics() { this.store.dispatch( reloadSystemDiagnostics({ request: { - nodewise: false + nodewise: false, + errorStrategy: 'banner' } }) );