mirror of https://github.com/apache/nifi.git
NIFI-12937: Adding error handling to the Parameter Context Listing page (#8555)
* NIFI-12937: - Adding error handling to the Parameter Context Listing page. * NIFI-12937: - Addressing review feedback. This closes #8555
This commit is contained in:
parent
039fd66911
commit
339a06a8c6
|
@ -17,7 +17,7 @@ const target = {
|
|||
console.log('Received Response from the Target:', proxyRes.statusCode, req.url);
|
||||
});
|
||||
},
|
||||
bypass: function(req, res, proxyOptions) {
|
||||
bypass: function (req) {
|
||||
if (req.url.startsWith('/nifi/')) {
|
||||
return req.url;
|
||||
}
|
||||
|
|
|
@ -89,6 +89,5 @@ export interface ParameterContextListingState {
|
|||
updateRequestEntity: ParameterContextUpdateRequestEntity | null;
|
||||
saving: boolean;
|
||||
loadedTimestamp: string;
|
||||
error: string | null;
|
||||
status: 'pending' | 'loading' | 'error' | 'success';
|
||||
status: 'pending' | 'loading' | 'success';
|
||||
}
|
||||
|
|
|
@ -35,8 +35,13 @@ export const loadParameterContextsSuccess = createAction(
|
|||
props<{ response: LoadParameterContextsResponse }>()
|
||||
);
|
||||
|
||||
export const parameterContextListingApiError = createAction(
|
||||
'[Parameter Context Listing] Load Parameter Context Listing Error',
|
||||
export const parameterContextListingSnackbarApiError = createAction(
|
||||
'[Parameter Context Listing] Load Parameter Context Listing Snackbar Api Error',
|
||||
props<{ error: string }>()
|
||||
);
|
||||
|
||||
export const parameterContextListingBannerApiError = createAction(
|
||||
'[Parameter Context Listing] Load Parameter Context Listing Banner Api Error',
|
||||
props<{ error: string }>()
|
||||
);
|
||||
|
||||
|
@ -100,6 +105,11 @@ export const deleteParameterContextUpdateRequest = createAction(
|
|||
'[Parameter Context Listing] Delete Parameter Context Update Request'
|
||||
);
|
||||
|
||||
export const deleteParameterContextUpdateRequestSuccess = createAction(
|
||||
'[Parameter Context Listing] Delete Parameter Context Update Request Success',
|
||||
props<{ response: PollParameterContextUpdateSuccess }>()
|
||||
);
|
||||
|
||||
export const editParameterContextComplete = createAction('[Parameter Context Listing] Edit Parameter Context Complete');
|
||||
|
||||
export const promptParameterContextDeletion = createAction(
|
||||
|
|
|
@ -18,13 +18,14 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects';
|
||||
import * as ParameterContextListingActions from './parameter-context-listing.actions';
|
||||
import * as ErrorActions from '../../../../state/error/error.actions';
|
||||
import {
|
||||
asyncScheduler,
|
||||
catchError,
|
||||
filter,
|
||||
from,
|
||||
interval,
|
||||
map,
|
||||
NEVER,
|
||||
Observable,
|
||||
of,
|
||||
switchMap,
|
||||
|
@ -39,15 +40,23 @@ import { Router } from '@angular/router';
|
|||
import { ParameterContextService } from '../../service/parameter-contexts.service';
|
||||
import { YesNoDialog } from '../../../../ui/common/yes-no-dialog/yes-no-dialog.component';
|
||||
import { EditParameterContext } from '../../ui/parameter-context-listing/edit-parameter-context/edit-parameter-context.component';
|
||||
import { selectParameterContexts, selectSaving, selectUpdateRequest } from './parameter-context-listing.selectors';
|
||||
import {
|
||||
selectParameterContexts,
|
||||
selectParameterContextStatus,
|
||||
selectSaving,
|
||||
selectUpdateRequest
|
||||
} from './parameter-context-listing.selectors';
|
||||
import {
|
||||
EditParameterRequest,
|
||||
EditParameterResponse,
|
||||
isDefinedAndNotNull,
|
||||
Parameter,
|
||||
ParameterContextUpdateRequest
|
||||
} from '../../../../state/shared';
|
||||
import { EditParameterDialog } from '../../../../ui/common/edit-parameter-dialog/edit-parameter-dialog.component';
|
||||
import { OkDialog } from '../../../../ui/common/ok-dialog/ok-dialog.component';
|
||||
import { ErrorHelper } from '../../../../service/error-helper.service';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
|
||||
@Injectable()
|
||||
export class ParameterContextListingEffects {
|
||||
|
@ -56,13 +65,15 @@ export class ParameterContextListingEffects {
|
|||
private store: Store<NiFiState>,
|
||||
private parameterContextService: ParameterContextService,
|
||||
private dialog: MatDialog,
|
||||
private router: Router
|
||||
private router: Router,
|
||||
private errorHelper: ErrorHelper
|
||||
) {}
|
||||
|
||||
loadParameterContexts$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(ParameterContextListingActions.loadParameterContexts),
|
||||
switchMap(() =>
|
||||
concatLatestFrom(() => this.store.select(selectParameterContextStatus)),
|
||||
switchMap(([, status]) =>
|
||||
from(this.parameterContextService.getParameterContexts()).pipe(
|
||||
map((response) =>
|
||||
ParameterContextListingActions.loadParameterContextsSuccess({
|
||||
|
@ -72,12 +83,8 @@ export class ParameterContextListingEffects {
|
|||
}
|
||||
})
|
||||
),
|
||||
catchError((error) =>
|
||||
of(
|
||||
ParameterContextListingActions.parameterContextListingApiError({
|
||||
error: error.error
|
||||
})
|
||||
)
|
||||
catchError((errorResponse: HttpErrorResponse) =>
|
||||
of(this.errorHelper.handleLoadingError(status, errorResponse))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -121,13 +128,15 @@ export class ParameterContextListingEffects {
|
|||
);
|
||||
};
|
||||
|
||||
dialogReference.componentInstance.addParameterContext.pipe(take(1)).subscribe((payload: any) => {
|
||||
this.store.dispatch(
|
||||
ParameterContextListingActions.createParameterContext({
|
||||
request: { payload }
|
||||
})
|
||||
);
|
||||
});
|
||||
dialogReference.componentInstance.addParameterContext
|
||||
.pipe(takeUntil(dialogReference.afterClosed()))
|
||||
.subscribe((payload: any) => {
|
||||
this.store.dispatch(
|
||||
ParameterContextListingActions.createParameterContext({
|
||||
request: { payload }
|
||||
})
|
||||
);
|
||||
});
|
||||
})
|
||||
),
|
||||
{ dispatch: false }
|
||||
|
@ -146,13 +155,18 @@ export class ParameterContextListingEffects {
|
|||
}
|
||||
})
|
||||
),
|
||||
catchError((error) =>
|
||||
of(
|
||||
ParameterContextListingActions.parameterContextListingApiError({
|
||||
error: error.error
|
||||
})
|
||||
)
|
||||
)
|
||||
catchError((errorResponse: HttpErrorResponse) => {
|
||||
if (this.errorHelper.showErrorInContext(errorResponse.status)) {
|
||||
return of(
|
||||
ParameterContextListingActions.parameterContextListingBannerApiError({
|
||||
error: errorResponse.error
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.dialog.closeAll();
|
||||
return of(this.errorHelper.fullScreenError(errorResponse));
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -169,6 +183,22 @@ export class ParameterContextListingEffects {
|
|||
{ dispatch: false }
|
||||
);
|
||||
|
||||
parameterContextListingBannerApiError$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(ParameterContextListingActions.parameterContextListingBannerApiError),
|
||||
map((action) => action.error),
|
||||
switchMap((error) => of(ErrorActions.addBannerError({ error })))
|
||||
)
|
||||
);
|
||||
|
||||
parameterContextListingSnackbarApiError$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(ParameterContextListingActions.parameterContextListingSnackbarApiError),
|
||||
map((action) => action.error),
|
||||
switchMap((error) => of(ErrorActions.snackBarError({ error })))
|
||||
)
|
||||
);
|
||||
|
||||
navigateToEditService$ = createEffect(
|
||||
() =>
|
||||
this.actions$.pipe(
|
||||
|
@ -194,13 +224,14 @@ export class ParameterContextListingEffects {
|
|||
}
|
||||
})
|
||||
),
|
||||
catchError((error) =>
|
||||
of(
|
||||
ParameterContextListingActions.parameterContextListingApiError({
|
||||
error: error.error
|
||||
catchError((errorResponse: HttpErrorResponse) => {
|
||||
this.router.navigate(['/parameter-contexts']);
|
||||
return of(
|
||||
ParameterContextListingActions.parameterContextListingSnackbarApiError({
|
||||
error: errorResponse.error
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -281,7 +312,7 @@ export class ParameterContextListingEffects {
|
|||
};
|
||||
|
||||
editDialogReference.componentInstance.editParameterContext
|
||||
.pipe(take(1))
|
||||
.pipe(takeUntil(editDialogReference.afterClosed()))
|
||||
.subscribe((payload: any) => {
|
||||
this.store.dispatch(
|
||||
ParameterContextListingActions.submitParameterContextUpdateRequest({
|
||||
|
@ -294,6 +325,8 @@ export class ParameterContextListingEffects {
|
|||
});
|
||||
|
||||
editDialogReference.afterClosed().subscribe((response) => {
|
||||
this.store.dispatch(ErrorActions.clearBannerErrors());
|
||||
|
||||
if (response != 'ROUTED') {
|
||||
this.store.dispatch(
|
||||
ParameterContextListingActions.selectParameterContext({
|
||||
|
@ -323,13 +356,18 @@ export class ParameterContextListingEffects {
|
|||
}
|
||||
})
|
||||
),
|
||||
catchError((error) =>
|
||||
of(
|
||||
ParameterContextListingActions.parameterContextListingApiError({
|
||||
error: error.error
|
||||
})
|
||||
)
|
||||
)
|
||||
catchError((errorResponse: HttpErrorResponse) => {
|
||||
if (this.errorHelper.showErrorInContext(errorResponse.status)) {
|
||||
return of(
|
||||
ParameterContextListingActions.parameterContextListingBannerApiError({
|
||||
error: errorResponse.error
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.dialog.closeAll();
|
||||
return of(this.errorHelper.fullScreenError(errorResponse));
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -369,29 +407,31 @@ export class ParameterContextListingEffects {
|
|||
pollParameterContextUpdateRequest$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(ParameterContextListingActions.pollParameterContextUpdateRequest),
|
||||
concatLatestFrom(() => this.store.select(selectUpdateRequest)),
|
||||
switchMap(([, updateRequest]) => {
|
||||
if (updateRequest) {
|
||||
return from(this.parameterContextService.pollParameterContextUpdate(updateRequest.request)).pipe(
|
||||
map((response) =>
|
||||
ParameterContextListingActions.pollParameterContextUpdateRequestSuccess({
|
||||
response: {
|
||||
requestEntity: response
|
||||
}
|
||||
})
|
||||
),
|
||||
catchError((error) =>
|
||||
of(
|
||||
ParameterContextListingActions.parameterContextListingApiError({
|
||||
error: error.error
|
||||
concatLatestFrom(() => this.store.select(selectUpdateRequest).pipe(isDefinedAndNotNull())),
|
||||
switchMap(([, updateRequest]) =>
|
||||
from(this.parameterContextService.pollParameterContextUpdate(updateRequest.request)).pipe(
|
||||
map((response) =>
|
||||
ParameterContextListingActions.pollParameterContextUpdateRequestSuccess({
|
||||
response: {
|
||||
requestEntity: response
|
||||
}
|
||||
})
|
||||
),
|
||||
catchError((errorResponse: HttpErrorResponse) => {
|
||||
this.store.dispatch(ParameterContextListingActions.stopPollingParameterContextUpdateRequest());
|
||||
|
||||
if (this.errorHelper.showErrorInContext(errorResponse.status)) {
|
||||
return of(
|
||||
ParameterContextListingActions.parameterContextListingBannerApiError({
|
||||
error: errorResponse.error
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return NEVER;
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
return of(this.errorHelper.fullScreenError(errorResponse));
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -399,14 +439,8 @@ export class ParameterContextListingEffects {
|
|||
this.actions$.pipe(
|
||||
ofType(ParameterContextListingActions.pollParameterContextUpdateRequestSuccess),
|
||||
map((action) => action.response),
|
||||
switchMap((response) => {
|
||||
const updateRequest: ParameterContextUpdateRequest = response.requestEntity.request;
|
||||
if (updateRequest.complete) {
|
||||
return of(ParameterContextListingActions.stopPollingParameterContextUpdateRequest());
|
||||
} else {
|
||||
return NEVER;
|
||||
}
|
||||
})
|
||||
filter((response) => response.requestEntity.request.complete),
|
||||
switchMap(() => of(ParameterContextListingActions.stopPollingParameterContextUpdateRequest()))
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -421,11 +455,19 @@ export class ParameterContextListingEffects {
|
|||
() =>
|
||||
this.actions$.pipe(
|
||||
ofType(ParameterContextListingActions.deleteParameterContextUpdateRequest),
|
||||
concatLatestFrom(() => this.store.select(selectUpdateRequest)),
|
||||
concatLatestFrom(() => this.store.select(selectUpdateRequest).pipe(isDefinedAndNotNull())),
|
||||
tap(([, updateRequest]) => {
|
||||
if (updateRequest) {
|
||||
this.parameterContextService.deleteParameterContextUpdate(updateRequest.request).subscribe();
|
||||
}
|
||||
this.parameterContextService
|
||||
.deleteParameterContextUpdate(updateRequest.request)
|
||||
.subscribe((response) => {
|
||||
this.store.dispatch(
|
||||
ParameterContextListingActions.deleteParameterContextUpdateRequestSuccess({
|
||||
response: {
|
||||
requestEntity: response
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
})
|
||||
),
|
||||
{ dispatch: false }
|
||||
|
@ -472,7 +514,7 @@ export class ParameterContextListingEffects {
|
|||
),
|
||||
catchError((error) =>
|
||||
of(
|
||||
ParameterContextListingActions.parameterContextListingApiError({
|
||||
ParameterContextListingActions.parameterContextListingSnackbarApiError({
|
||||
error: error.error
|
||||
})
|
||||
)
|
||||
|
|
|
@ -25,10 +25,12 @@ import {
|
|||
editParameterContextComplete,
|
||||
loadParameterContexts,
|
||||
loadParameterContextsSuccess,
|
||||
parameterContextListingApiError,
|
||||
parameterContextListingSnackbarApiError,
|
||||
parameterContextListingBannerApiError,
|
||||
pollParameterContextUpdateRequestSuccess,
|
||||
submitParameterContextUpdateRequest,
|
||||
submitParameterContextUpdateRequestSuccess
|
||||
submitParameterContextUpdateRequestSuccess,
|
||||
deleteParameterContextUpdateRequestSuccess
|
||||
} from './parameter-context-listing.actions';
|
||||
import { ParameterContextUpdateRequestEntity, Revision } from '../../../../state/shared';
|
||||
|
||||
|
@ -37,7 +39,6 @@ export const initialState: ParameterContextListingState = {
|
|||
updateRequestEntity: null,
|
||||
saving: false,
|
||||
loadedTimestamp: '',
|
||||
error: null,
|
||||
status: 'pending'
|
||||
};
|
||||
|
||||
|
@ -54,11 +55,9 @@ export const parameterContextListingReducer = createReducer(
|
|||
error: null,
|
||||
status: 'success' as const
|
||||
})),
|
||||
on(parameterContextListingApiError, (state, { error }) => ({
|
||||
on(parameterContextListingSnackbarApiError, parameterContextListingBannerApiError, (state) => ({
|
||||
...state,
|
||||
saving: false,
|
||||
error,
|
||||
status: 'error' as const
|
||||
saving: false
|
||||
})),
|
||||
on(createParameterContext, (state) => ({
|
||||
...state,
|
||||
|
@ -74,10 +73,15 @@ export const parameterContextListingReducer = createReducer(
|
|||
...state,
|
||||
saving: true
|
||||
})),
|
||||
on(submitParameterContextUpdateRequestSuccess, pollParameterContextUpdateRequestSuccess, (state, { response }) => ({
|
||||
...state,
|
||||
updateRequestEntity: response.requestEntity
|
||||
})),
|
||||
on(
|
||||
submitParameterContextUpdateRequestSuccess,
|
||||
pollParameterContextUpdateRequestSuccess,
|
||||
deleteParameterContextUpdateRequestSuccess,
|
||||
(state, { response }) => ({
|
||||
...state,
|
||||
updateRequestEntity: response.requestEntity
|
||||
})
|
||||
),
|
||||
on(editParameterContextComplete, (state) => {
|
||||
return produce(state, (draftState) => {
|
||||
const updateRequestEntity: ParameterContextUpdateRequestEntity | null = draftState.updateRequestEntity;
|
||||
|
|
|
@ -54,6 +54,11 @@ export const selectParameterContexts = createSelector(
|
|||
(state: ParameterContextListingState) => state.parameterContexts
|
||||
);
|
||||
|
||||
export const selectParameterContextStatus = createSelector(
|
||||
selectParameterContextListingState,
|
||||
(state: ParameterContextListingState) => state.status
|
||||
);
|
||||
|
||||
export const selectContext = (id: string) =>
|
||||
createSelector(selectParameterContexts, (parameterContexts: ParameterContextEntity[]) =>
|
||||
parameterContexts.find((entity) => id == entity.id)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
<h2 mat-dialog-title>{{ this.isNew ? 'Add' : 'Edit' }} Parameter Context</h2>
|
||||
<form class="parameter-context-edit-form" [formGroup]="editParameterContextForm">
|
||||
<error-banner></error-banner>
|
||||
@if ((updateRequest | async)!; as requestEntity) {
|
||||
<mat-dialog-content>
|
||||
<div class="results-content flex gap-x-8">
|
||||
|
@ -26,12 +27,21 @@
|
|||
@for (updateStep of requestEntity.request.updateSteps; track updateStep) {
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="value">{{ updateStep.description }}</div>
|
||||
@if (updateStep.complete) {
|
||||
<div class="fa fa-check complete"></div>
|
||||
@if (updateStep.failureReason) {
|
||||
<div class="fa fa-times warn-default"></div>
|
||||
} @else {
|
||||
<div class="fa fa-spin fa-circle-o-notch"></div>
|
||||
@if (updateStep.complete) {
|
||||
<div class="fa fa-check complete"></div>
|
||||
} @else {
|
||||
<div class="fa fa-spin fa-circle-o-notch"></div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
@if (updateStep.failureReason) {
|
||||
<div class="text-xs ml-2">
|
||||
{{ updateStep.failureReason }}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -40,6 +40,7 @@ import { ProcessGroupReferences } from '../process-group-references/process-grou
|
|||
import { ParameterContextInheritance } from '../parameter-context-inheritance/parameter-context-inheritance.component';
|
||||
import { ParameterReferences } from '../../../../../ui/common/parameter-references/parameter-references.component';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { ErrorBanner } from '../../../../../ui/common/error-banner/error-banner.component';
|
||||
|
||||
@Component({
|
||||
selector: 'edit-parameter-context',
|
||||
|
@ -61,7 +62,8 @@ import { RouterLink } from '@angular/router';
|
|||
ProcessGroupReferences,
|
||||
ParameterContextInheritance,
|
||||
ParameterReferences,
|
||||
RouterLink
|
||||
RouterLink,
|
||||
ErrorBanner
|
||||
],
|
||||
styleUrls: ['./edit-parameter-context.component.scss']
|
||||
})
|
||||
|
|
|
@ -98,7 +98,7 @@ export class ParameterContextTable {
|
|||
}
|
||||
|
||||
canManageAccessPolicies(): boolean {
|
||||
return this.flowConfiguration.supportsManagedAuthorizer && this.currentUser.tenantsPermissions.canRead;
|
||||
return this.flowConfiguration?.supportsManagedAuthorizer && this.currentUser.tenantsPermissions.canRead;
|
||||
}
|
||||
|
||||
canGoToParameterProvider(entity: ParameterContextEntity): boolean {
|
||||
|
|
|
@ -143,6 +143,6 @@
|
|||
<div class="fa fa-check complete"></div>
|
||||
</ng-template>
|
||||
<ng-template #stepError>
|
||||
<div class="fa fa-times text-red-400"></div>
|
||||
<div class="fa fa-times warn-default"></div>
|
||||
</ng-template>
|
||||
<ng-template #stepNotStarted><div class="w-3.5"></div></ng-template>
|
||||
|
|
|
@ -164,6 +164,6 @@
|
|||
<div class="fa fa-check complete"></div>
|
||||
</ng-template>
|
||||
<ng-template #stepError>
|
||||
<div class="fa fa-times text-red-400"></div>
|
||||
<div class="fa fa-times warn-default"></div>
|
||||
</ng-template>
|
||||
<ng-template #stepNotStarted><div class="w-3.5"></div></ng-template>
|
||||
|
|
|
@ -287,6 +287,7 @@
|
|||
fill: $accent-palette-lighter !important;
|
||||
}
|
||||
|
||||
.warn-default,
|
||||
.stale,
|
||||
.locally-modified-and-stale {
|
||||
color: $warn-palette-default !important;
|
||||
|
|
|
@ -85,7 +85,10 @@
|
|||
$color-palette: map.get($theme, $palette);
|
||||
|
||||
$default: mat.get-color-from-palette($color-palette, default);
|
||||
$high-contrast: mat.get-color-from-palette($color-palette, if(luminosity($default) > luminosity($surface), lighter, darker));
|
||||
$high-contrast: mat.get-color-from-palette(
|
||||
$color-palette,
|
||||
if(luminosity($default) > luminosity($surface), lighter, darker)
|
||||
);
|
||||
$on-surface: ensure-contrast($default, $surface, $high-contrast);
|
||||
|
||||
@return $on-surface;
|
||||
|
|
Loading…
Reference in New Issue