mirror of https://github.com/apache/nifi.git
[NIFI-13099] status history error handling (#8703)
* [NIFI-13099] - Error handling for Status History * Error handling for current user * Error handling for extension types * Error handling for flow configuration * Error handling for component state * Error handling for cluster summary * Error handling for System Diagnostics * review feedback * use SystemDiagnosticsActions.systemDiagnosticsSnackbarError * review feedback * review feedback * use snackbar This closes #8703
This commit is contained in:
parent
a230eba67b
commit
658e83b7ec
|
@ -21,7 +21,7 @@
|
|||
</header>
|
||||
<div class="px-5 flex-1 flex flex-col gap-y-2">
|
||||
<h3 class="text-xl bold primary-color">NiFi Cluster</h3>
|
||||
|
||||
<error-banner></error-banner>
|
||||
@if (getTabLinks(); as tabs) {
|
||||
<!-- Don't show the tab bar if there is only 1 tab to show -->
|
||||
<div class="cluster-tabs" [class.hidden]="tabs.length === 1">
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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<NiFiState>,
|
||||
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(
|
||||
|
|
|
@ -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 }>()
|
||||
|
|
|
@ -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
|
||||
}]`
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
|
|
@ -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`);
|
||||
|
|
|
@ -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
|
||||
}]`
|
||||
})
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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
|
||||
}))
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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)))
|
||||
)
|
||||
);
|
||||
})
|
||||
|
|
|
@ -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
|
||||
}))
|
||||
);
|
||||
|
|
|
@ -45,6 +45,5 @@ export interface CurrentUser {
|
|||
|
||||
export interface CurrentUserState {
|
||||
user: CurrentUser;
|
||||
error: string | null;
|
||||
status: 'pending' | 'loading' | 'error' | 'success';
|
||||
status: 'pending' | 'loading' | 'success';
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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
|
||||
}]`
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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
|
||||
}))
|
||||
);
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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
|
||||
}]`
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -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
|
||||
}))
|
||||
);
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
|
|
@ -75,6 +75,5 @@ export interface StatusHistoryResponse {
|
|||
export interface StatusHistoryState {
|
||||
statusHistory: StatusHistoryEntity;
|
||||
loadedTimestamp: string;
|
||||
error: string | null;
|
||||
status: 'pending' | 'loading' | 'error' | 'success';
|
||||
}
|
||||
|
|
|
@ -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 }>()
|
||||
);
|
||||
|
||||
|
|
|
@ -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<NiFiState>,
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}))
|
||||
);
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }>()
|
||||
);
|
||||
|
||||
|
|
|
@ -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 })))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
})),
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
<div class="component-state-dialog" tabindex="0">
|
||||
<h2 mat-dialog-title>Component State</h2>
|
||||
<error-banner></error-banner>
|
||||
<mat-dialog-content>
|
||||
<div class="flex flex-col justify-between gap-y-5">
|
||||
@if (componentName$ | async; as componentName) {
|
||||
|
|
|
@ -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 : [];
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<div resizable (resized)="resized()" [minHeight]="720" [minWidth]="887" class="flex flex-col status-history-container">
|
||||
@if (statusHistoryState$ | async; as statusHistoryState) {
|
||||
<h2 mat-dialog-title>Status History</h2>
|
||||
<error-banner></error-banner>
|
||||
<div class="status-history flex flex-col grow">
|
||||
<mat-dialog-content class="grow flex flex-1">
|
||||
<form [formGroup]="statusHistoryForm" class="flex flex-1 h-full">
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
@if ((systemDiagnostics$ | async)?.aggregateSnapshot; as systemDiagnostics) {
|
||||
<h2 mat-dialog-title>System Diagnostics</h2>
|
||||
<error-banner></error-banner>
|
||||
<div class="system-diagnostics">
|
||||
<mat-dialog-content>
|
||||
<div class="dialog-content">
|
||||
|
|
|
@ -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'
|
||||
}
|
||||
})
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue