mirror of https://github.com/apache/nifi.git
NIFI-12767: Error handling in Provenance and Lineage (#8386)
* NIFI-12767: - Error handling in Provenance and Lineage. * NIFI-12767: - Addressing review feedback. * NIFI-12767: - Restoring empty initial state for completed request that allows showing a banner error over an empty table instead of an empty page. * NIFI-12767: - Restoring error state to ensure that the loading spinner stops on error. This closes #8386
This commit is contained in:
parent
4f030fefca
commit
da8f86b7e7
|
@ -19,7 +19,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
|
||||
import { AddTenantToPolicyDialog } from './add-tenant-to-policy-dialog.component';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { AddTenantToPolicyDialogRequest } from '../../../state/access-policy';
|
||||
|
||||
describe('AddTenantToPolicyDialog', () => {
|
||||
|
@ -68,7 +68,7 @@ describe('AddTenantToPolicyDialog', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [AddTenantToPolicyDialog, BrowserAnimationsModule],
|
||||
imports: [AddTenantToPolicyDialog, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }]
|
||||
});
|
||||
fixture = TestBed.createComponent(AddTenantToPolicyDialog);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { OverridePolicyDialog } from './override-policy-dialog.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('OverridePolicyDialog', () => {
|
||||
let component: OverridePolicyDialog;
|
||||
|
@ -26,7 +26,7 @@ describe('OverridePolicyDialog', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [OverridePolicyDialog, BrowserAnimationsModule]
|
||||
imports: [OverridePolicyDialog, NoopAnimationsModule]
|
||||
});
|
||||
fixture = TestBed.createComponent(OverridePolicyDialog);
|
||||
component = fixture.componentInstance;
|
||||
|
|
|
@ -23,7 +23,7 @@ import { provideMockStore } from '@ngrx/store/testing';
|
|||
import { initialState } from '../../../../../state/flow/flow.reducer';
|
||||
import { CreateConnectionDialogRequest } from '../../../../../state/flow';
|
||||
import { ComponentType, DocumentedType } from '../../../../../../../state/shared';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
describe('CreateConnection', () => {
|
||||
|
@ -366,7 +366,7 @@ describe('CreateConnection', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CreateConnection, BrowserAnimationsModule],
|
||||
imports: [CreateConnection, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }, provideMockStore({ initialState })]
|
||||
});
|
||||
fixture = TestBed.createComponent(CreateConnection);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DestinationProcessGroup } from './destination-process-group.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('DestinationProcessGroup', () => {
|
||||
let component: DestinationProcessGroup;
|
||||
|
@ -26,7 +26,7 @@ describe('DestinationProcessGroup', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [BrowserAnimationsModule, DestinationProcessGroup]
|
||||
imports: [NoopAnimationsModule, DestinationProcessGroup]
|
||||
});
|
||||
fixture = TestBed.createComponent(DestinationProcessGroup);
|
||||
component = fixture.componentInstance;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DestinationRemoteProcessGroup } from './destination-remote-process-group.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('DestinationRemoteProcessGroup', () => {
|
||||
let component: DestinationRemoteProcessGroup;
|
||||
|
@ -26,7 +26,7 @@ describe('DestinationRemoteProcessGroup', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [BrowserAnimationsModule, DestinationRemoteProcessGroup]
|
||||
imports: [NoopAnimationsModule, DestinationRemoteProcessGroup]
|
||||
});
|
||||
fixture = TestBed.createComponent(DestinationRemoteProcessGroup);
|
||||
component = fixture.componentInstance;
|
||||
|
|
|
@ -24,7 +24,7 @@ import { ComponentType } from '../../../../../../../state/shared';
|
|||
import { MockStore, provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../../state/flow/flow.reducer';
|
||||
import { selectPrioritizerTypes } from '../../../../../../../state/extension-types/extension-types.selectors';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('EditConnectionComponent', () => {
|
||||
let store: MockStore;
|
||||
|
@ -129,7 +129,7 @@ describe('EditConnectionComponent', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [EditConnectionComponent, BrowserAnimationsModule],
|
||||
imports: [EditConnectionComponent, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }, provideMockStore({ initialState })]
|
||||
});
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SourceProcessGroup } from './source-process-group.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('SourceProcessGroup', () => {
|
||||
let component: SourceProcessGroup;
|
||||
|
@ -26,7 +26,7 @@ describe('SourceProcessGroup', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [BrowserAnimationsModule, SourceProcessGroup]
|
||||
imports: [NoopAnimationsModule, SourceProcessGroup]
|
||||
});
|
||||
fixture = TestBed.createComponent(SourceProcessGroup);
|
||||
component = fixture.componentInstance;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SourceRemoteProcessGroup } from './source-remote-process-group.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('SourceRemoteProcessGroup', () => {
|
||||
let component: SourceRemoteProcessGroup;
|
||||
|
@ -26,7 +26,7 @@ describe('SourceRemoteProcessGroup', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [BrowserAnimationsModule, SourceRemoteProcessGroup]
|
||||
imports: [NoopAnimationsModule, SourceRemoteProcessGroup]
|
||||
});
|
||||
fixture = TestBed.createComponent(SourceRemoteProcessGroup);
|
||||
component = fixture.componentInstance;
|
||||
|
|
|
@ -23,7 +23,7 @@ import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|||
import { ComponentType } from '../../../../../../../state/shared';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../../state/flow/flow.reducer';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { EMPTY } from 'rxjs';
|
||||
|
||||
describe('ImportFromRegistry', () => {
|
||||
|
@ -111,7 +111,7 @@ describe('ImportFromRegistry', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ImportFromRegistry, BrowserAnimationsModule],
|
||||
imports: [ImportFromRegistry, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }, provideMockStore({ initialState })]
|
||||
});
|
||||
fixture = TestBed.createComponent(ImportFromRegistry);
|
||||
|
|
|
@ -23,7 +23,7 @@ import { ComponentType } from '../../../../../../../state/shared';
|
|||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../../state/flow/flow.reducer';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('CreatePort', () => {
|
||||
let component: CreatePort;
|
||||
|
@ -43,7 +43,7 @@ describe('CreatePort', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CreatePort, BrowserAnimationsModule],
|
||||
imports: [CreatePort, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }, provideMockStore({ initialState })]
|
||||
});
|
||||
fixture = TestBed.createComponent(CreatePort);
|
||||
|
|
|
@ -23,7 +23,7 @@ import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|||
import { ComponentType } from '../../../../../../../state/shared';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../../state/flow/flow.reducer';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('EditPort', () => {
|
||||
let component: EditPort;
|
||||
|
@ -95,7 +95,7 @@ describe('EditPort', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [EditPort, BrowserAnimationsModule],
|
||||
imports: [EditPort, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }, provideMockStore({ initialState })]
|
||||
});
|
||||
fixture = TestBed.createComponent(EditPort);
|
||||
|
|
|
@ -23,7 +23,7 @@ import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|||
import { ComponentType } from '../../../../../../../state/shared';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../../state/flow/flow.reducer';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('CreateProcessGroup', () => {
|
||||
let component: CreateProcessGroup;
|
||||
|
@ -155,7 +155,7 @@ describe('CreateProcessGroup', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CreateProcessGroup, BrowserAnimationsModule],
|
||||
imports: [CreateProcessGroup, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }, provideMockStore({ initialState })]
|
||||
});
|
||||
fixture = TestBed.createComponent(CreateProcessGroup);
|
||||
|
|
|
@ -19,7 +19,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
|
||||
import { EditProcessGroup } from './edit-process-group.component';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('EditProcessGroup', () => {
|
||||
let component: EditProcessGroup;
|
||||
|
@ -106,7 +106,7 @@ describe('EditProcessGroup', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [EditProcessGroup, BrowserAnimationsModule],
|
||||
imports: [EditProcessGroup, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }]
|
||||
});
|
||||
fixture = TestBed.createComponent(EditProcessGroup);
|
||||
|
|
|
@ -23,7 +23,7 @@ import { ComponentType } from '../../../../../../../state/shared';
|
|||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../../state/flow/flow.reducer';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('GroupComponents', () => {
|
||||
let component: GroupComponents;
|
||||
|
@ -860,7 +860,7 @@ describe('GroupComponents', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [GroupComponents, BrowserAnimationsModule],
|
||||
imports: [GroupComponents, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }, provideMockStore({ initialState })]
|
||||
});
|
||||
fixture = TestBed.createComponent(GroupComponents);
|
||||
|
|
|
@ -23,7 +23,7 @@ import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../../../../state/extension-types/extension-types.reducer';
|
||||
import { ComponentType } from '../../../../../../../state/shared';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('CreateProcessor', () => {
|
||||
let component: CreateProcessor;
|
||||
|
@ -59,7 +59,7 @@ describe('CreateProcessor', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CreateProcessor, BrowserAnimationsModule],
|
||||
imports: [CreateProcessor, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }, provideMockStore({ initialState })]
|
||||
});
|
||||
fixture = TestBed.createComponent(CreateProcessor);
|
||||
|
|
|
@ -21,7 +21,7 @@ import { EditProcessor } from './edit-processor.component';
|
|||
import { EditComponentDialogRequest } from '../../../../../state/flow';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { ComponentType } from '../../../../../../../state/shared';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { Component } from '@angular/core';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../../../../state/error/error.reducer';
|
||||
|
@ -731,7 +731,7 @@ describe('EditProcessor', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [EditProcessor, MockErrorBanner, BrowserAnimationsModule],
|
||||
imports: [EditProcessor, MockErrorBanner, NoopAnimationsModule],
|
||||
providers: [
|
||||
{ provide: MAT_DIALOG_DATA, useValue: data },
|
||||
provideMockStore({
|
||||
|
|
|
@ -26,7 +26,7 @@ import { RouterModule } from '@angular/router';
|
|||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('LoginForm', () => {
|
||||
let component: LoginForm;
|
||||
|
@ -37,7 +37,7 @@ describe('LoginForm', () => {
|
|||
declarations: [LoginForm],
|
||||
imports: [
|
||||
HttpClientTestingModule,
|
||||
BrowserAnimationsModule,
|
||||
NoopAnimationsModule,
|
||||
MatFormFieldModule,
|
||||
RouterModule,
|
||||
RouterTestingModule,
|
||||
|
|
|
@ -21,7 +21,7 @@ import { EditParameterContext } from './edit-parameter-context.component';
|
|||
import { EditParameterContextRequest, ParameterContextEntity } from '../../../state/parameter-context-listing';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { of } from 'rxjs';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../state/parameter-context-listing/parameter-context-listing.reducer';
|
||||
|
||||
|
@ -234,7 +234,7 @@ describe('EditParameterContext', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [EditParameterContext, BrowserAnimationsModule],
|
||||
imports: [EditParameterContext, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }, provideMockStore({ initialState })]
|
||||
});
|
||||
fixture = TestBed.createComponent(EditParameterContext);
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { NiFiCommon } from '../../../service/nifi-common.service';
|
||||
import { ProvenanceRequest } from '../state/provenance-event-listing';
|
||||
import { LineageRequest } from '../state/lineage';
|
||||
|
||||
|
@ -26,10 +25,7 @@ import { LineageRequest } from '../state/lineage';
|
|||
export class ProvenanceService {
|
||||
private static readonly API: string = '../nifi-api';
|
||||
|
||||
constructor(
|
||||
private httpClient: HttpClient,
|
||||
private nifiCommon: NiFiCommon
|
||||
) {}
|
||||
constructor(private httpClient: HttpClient) {}
|
||||
|
||||
getSearchOptions(): Observable<any> {
|
||||
return this.httpClient.get(`${ProvenanceService.API}/provenance/search-options`);
|
||||
|
|
|
@ -66,7 +66,7 @@ export interface Lineage {
|
|||
}
|
||||
|
||||
export interface LineageState {
|
||||
lineage: Lineage | null;
|
||||
error: string | null;
|
||||
activeLineage: Lineage | null;
|
||||
completedLineage: Lineage;
|
||||
status: 'pending' | 'loading' | 'error' | 'success';
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@ export const stopPollingLineageQuery = createAction('[Lineage] Stop Polling Line
|
|||
|
||||
export const deleteLineageQuery = createAction('[Lineage] Delete Lineage Query');
|
||||
|
||||
export const deleteLineageQuerySuccess = createAction('[Lineage] Delete Lineage Query Success');
|
||||
|
||||
export const lineageApiError = createAction(
|
||||
'[Lineage] Load Parameter Context Listing Error',
|
||||
props<{ error: string }>()
|
||||
|
|
|
@ -18,15 +18,18 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects';
|
||||
import * as LineageActions from './lineage.actions';
|
||||
import * as ProvenanceActions from '../provenance-event-listing/provenance-event-listing.actions';
|
||||
import { asyncScheduler, catchError, from, interval, map, NEVER, of, switchMap, takeUntil, tap } from 'rxjs';
|
||||
import { asyncScheduler, catchError, filter, from, interval, map, of, switchMap, takeUntil, tap } from 'rxjs';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { NiFiState } from '../../../../state';
|
||||
import { ProvenanceService } from '../../service/provenance.service';
|
||||
import { Lineage } from './index';
|
||||
import { selectClusterNodeId } from '../provenance-event-listing/provenance-event-listing.selectors';
|
||||
import { selectLineageId } from './lineage.selectors';
|
||||
import { selectActiveLineageId } from './lineage.selectors';
|
||||
import * as ErrorActions from '../../../../state/error/error.actions';
|
||||
import { ErrorHelper } from '../../../../service/error-helper.service';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { isDefinedAndNotNull } from '../../../../state/shared';
|
||||
|
||||
@Injectable()
|
||||
export class LineageEffects {
|
||||
|
@ -34,6 +37,7 @@ export class LineageEffects {
|
|||
private actions$: Actions,
|
||||
private store: Store<NiFiState>,
|
||||
private provenanceService: ProvenanceService,
|
||||
private errorHelper: ErrorHelper,
|
||||
private dialog: MatDialog
|
||||
) {}
|
||||
|
||||
|
@ -50,19 +54,18 @@ export class LineageEffects {
|
|||
}
|
||||
})
|
||||
),
|
||||
catchError((error) => {
|
||||
this.store.dispatch(
|
||||
ProvenanceActions.showOkDialog({
|
||||
title: 'Error',
|
||||
message: error.error
|
||||
})
|
||||
);
|
||||
catchError((errorResponse: HttpErrorResponse) => {
|
||||
if (this.errorHelper.showErrorInContext(errorResponse.status)) {
|
||||
return of(
|
||||
LineageActions.lineageApiError({
|
||||
error: errorResponse.error
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.store.dispatch(LineageActions.stopPollingLineageQuery());
|
||||
|
||||
return of(
|
||||
LineageActions.lineageApiError({
|
||||
error: error.error
|
||||
})
|
||||
);
|
||||
return of(this.errorHelper.fullScreenError(errorResponse));
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
|
@ -100,29 +103,34 @@ export class LineageEffects {
|
|||
pollLineageQuery$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(LineageActions.pollLineageQuery),
|
||||
concatLatestFrom(() => [this.store.select(selectLineageId), this.store.select(selectClusterNodeId)]),
|
||||
switchMap(([, id, clusterNodeId]) => {
|
||||
if (id) {
|
||||
return from(this.provenanceService.getLineageQuery(id, clusterNodeId)).pipe(
|
||||
map((response) =>
|
||||
LineageActions.pollLineageQuerySuccess({
|
||||
response: {
|
||||
lineage: response.lineage
|
||||
}
|
||||
})
|
||||
),
|
||||
catchError((error) =>
|
||||
of(
|
||||
concatLatestFrom(() => [
|
||||
this.store.select(selectActiveLineageId).pipe(isDefinedAndNotNull()),
|
||||
this.store.select(selectClusterNodeId)
|
||||
]),
|
||||
switchMap(([, id, clusterNodeId]) =>
|
||||
from(this.provenanceService.getLineageQuery(id, clusterNodeId)).pipe(
|
||||
map((response) =>
|
||||
LineageActions.pollLineageQuerySuccess({
|
||||
response: {
|
||||
lineage: response.lineage
|
||||
}
|
||||
})
|
||||
),
|
||||
catchError((errorResponse: HttpErrorResponse) => {
|
||||
if (this.errorHelper.showErrorInContext(errorResponse.status)) {
|
||||
return of(
|
||||
LineageActions.lineageApiError({
|
||||
error: error.error
|
||||
error: errorResponse.error
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return NEVER;
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.store.dispatch(LineageActions.stopPollingLineageQuery());
|
||||
|
||||
return of(this.errorHelper.fullScreenError(errorResponse));
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -130,15 +138,8 @@ export class LineageEffects {
|
|||
this.actions$.pipe(
|
||||
ofType(LineageActions.pollLineageQuerySuccess),
|
||||
map((action) => action.response),
|
||||
switchMap((response) => {
|
||||
const query: Lineage = response.lineage;
|
||||
if (query.finished) {
|
||||
this.dialog.closeAll();
|
||||
return of(LineageActions.stopPollingLineageQuery());
|
||||
} else {
|
||||
return NEVER;
|
||||
}
|
||||
})
|
||||
filter((response) => response.lineage.finished),
|
||||
switchMap(() => of(LineageActions.stopPollingLineageQuery()))
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -149,17 +150,26 @@ export class LineageEffects {
|
|||
)
|
||||
);
|
||||
|
||||
deleteLineageQuery$ = createEffect(
|
||||
() =>
|
||||
this.actions$.pipe(
|
||||
ofType(LineageActions.deleteLineageQuery),
|
||||
concatLatestFrom(() => [this.store.select(selectLineageId), this.store.select(selectClusterNodeId)]),
|
||||
tap(([, id, clusterNodeId]) => {
|
||||
if (id) {
|
||||
this.provenanceService.deleteLineageQuery(id, clusterNodeId).subscribe();
|
||||
}
|
||||
})
|
||||
),
|
||||
{ dispatch: false }
|
||||
deleteLineageQuery$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(LineageActions.deleteLineageQuery),
|
||||
concatLatestFrom(() => [this.store.select(selectActiveLineageId), this.store.select(selectClusterNodeId)]),
|
||||
tap(([, id, clusterNodeId]) => {
|
||||
if (id) {
|
||||
this.provenanceService.deleteLineageQuery(id, clusterNodeId).subscribe();
|
||||
}
|
||||
}),
|
||||
switchMap(() => of(LineageActions.deleteLineageQuerySuccess()))
|
||||
)
|
||||
);
|
||||
|
||||
lineageApiError$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(LineageActions.lineageApiError),
|
||||
tap(() => {
|
||||
this.store.dispatch(LineageActions.stopPollingLineageQuery());
|
||||
}),
|
||||
switchMap(({ error }) => of(ErrorActions.addBannerError({ error })))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -18,16 +18,32 @@
|
|||
import { createReducer, on } from '@ngrx/store';
|
||||
import { LineageState } from './index';
|
||||
import {
|
||||
deleteLineageQuerySuccess,
|
||||
lineageApiError,
|
||||
pollLineageQuerySuccess,
|
||||
resetLineage,
|
||||
submitLineageQuery,
|
||||
submitLineageQuerySuccess
|
||||
} from './lineage.actions';
|
||||
import { produce } from 'immer';
|
||||
|
||||
export const initialState: LineageState = {
|
||||
lineage: null,
|
||||
error: null,
|
||||
activeLineage: null,
|
||||
completedLineage: {
|
||||
id: '',
|
||||
uri: '',
|
||||
submissionTime: '',
|
||||
expiration: '',
|
||||
percentCompleted: 0,
|
||||
finished: false,
|
||||
request: {
|
||||
lineageRequestType: 'FLOWFILE'
|
||||
},
|
||||
results: {
|
||||
nodes: [],
|
||||
links: []
|
||||
}
|
||||
},
|
||||
status: 'pending'
|
||||
};
|
||||
|
||||
|
@ -40,15 +56,24 @@ export const lineageReducer = createReducer(
|
|||
...state,
|
||||
status: 'loading' as const
|
||||
})),
|
||||
on(submitLineageQuerySuccess, pollLineageQuerySuccess, (state, { response }) => ({
|
||||
on(submitLineageQuerySuccess, pollLineageQuerySuccess, (state, { response }) => {
|
||||
return produce(state, (draftState) => {
|
||||
const lineage = response.lineage;
|
||||
draftState.activeLineage = lineage;
|
||||
|
||||
// if the query has finished save it as completed, the active query will be reset after deletion
|
||||
if (lineage.finished) {
|
||||
draftState.completedLineage = lineage;
|
||||
draftState.status = 'success' as const;
|
||||
}
|
||||
});
|
||||
}),
|
||||
on(deleteLineageQuerySuccess, (state) => ({
|
||||
...state,
|
||||
lineage: response.lineage,
|
||||
error: null,
|
||||
status: 'success' as const
|
||||
activeLineage: null
|
||||
})),
|
||||
on(lineageApiError, (state, { error }) => ({
|
||||
on(lineageApiError, (state) => ({
|
||||
...state,
|
||||
error,
|
||||
status: 'error' as const
|
||||
}))
|
||||
);
|
||||
|
|
|
@ -24,8 +24,11 @@ export const selectLineageState = createSelector(
|
|||
(state: ProvenanceState) => state[lineageFeatureKey]
|
||||
);
|
||||
|
||||
export const selectStatus = createSelector(selectLineageState, (state: LineageState) => state.status);
|
||||
export const selectActiveLineage = createSelector(selectLineageState, (state: LineageState) => state.activeLineage);
|
||||
|
||||
export const selectLineage = createSelector(selectLineageState, (state: LineageState) => state.lineage);
|
||||
export const selectCompletedLineage = createSelector(
|
||||
selectLineageState,
|
||||
(state: LineageState) => state.completedLineage
|
||||
);
|
||||
|
||||
export const selectLineageId = createSelector(selectLineage, (state: Lineage | null) => state?.id);
|
||||
export const selectActiveLineageId = createSelector(selectActiveLineage, (state: Lineage | null) => state?.id);
|
||||
|
|
|
@ -103,8 +103,8 @@ export interface Provenance {
|
|||
export interface ProvenanceEventListingState {
|
||||
options: ProvenanceOptions | null;
|
||||
request: ProvenanceRequest | null;
|
||||
provenance: Provenance | null;
|
||||
activeProvenance: Provenance | null;
|
||||
completedProvenance: Provenance;
|
||||
loadedTimestamp: string;
|
||||
error: string | null;
|
||||
status: 'pending' | 'loading' | 'error' | 'success';
|
||||
}
|
||||
|
|
|
@ -61,6 +61,8 @@ export const stopPollingProvenanceQuery = createAction('[Provenance Event Listin
|
|||
|
||||
export const deleteProvenanceQuery = createAction('[Provenance Event Listing] Delete Provenance Query');
|
||||
|
||||
export const deleteProvenanceQuerySuccess = createAction('[Provenance Event Listing] Delete Provenance Query Success');
|
||||
|
||||
export const provenanceApiError = createAction(
|
||||
'[Provenance Event Listing] Provenance Api Error',
|
||||
props<{ error: string }>()
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects';
|
||||
import * as ProvenanceEventListingActions from './provenance-event-listing.actions';
|
||||
import { asyncScheduler, catchError, from, interval, map, NEVER, of, switchMap, take, takeUntil, tap } from 'rxjs';
|
||||
import { asyncScheduler, catchError, filter, from, interval, map, of, switchMap, take, takeUntil, tap } from 'rxjs';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { NiFiState } from '../../../../state';
|
||||
|
@ -27,7 +27,7 @@ import { OkDialog } from '../../../../ui/common/ok-dialog/ok-dialog.component';
|
|||
import { ProvenanceService } from '../../service/provenance.service';
|
||||
import {
|
||||
selectClusterNodeId,
|
||||
selectProvenanceId,
|
||||
selectActiveProvenanceId,
|
||||
selectProvenanceOptions,
|
||||
selectProvenanceRequest,
|
||||
selectTimeOffset
|
||||
|
@ -37,6 +37,10 @@ import { ProvenanceSearchDialog } from '../../ui/provenance-event-listing/proven
|
|||
import { selectAbout } from '../../../../state/about/about.selectors';
|
||||
import { ProvenanceEventDialog } from '../../../../ui/common/provenance-event-dialog/provenance-event-dialog.component';
|
||||
import { CancelDialog } from '../../../../ui/common/cancel-dialog/cancel-dialog.component';
|
||||
import * as ErrorActions from '../../../../state/error/error.actions';
|
||||
import { ErrorHelper } from '../../../../service/error-helper.service';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { isDefinedAndNotNull } from '../../../../state/shared';
|
||||
|
||||
@Injectable()
|
||||
export class ProvenanceEventListingEffects {
|
||||
|
@ -44,6 +48,7 @@ export class ProvenanceEventListingEffects {
|
|||
private actions$: Actions,
|
||||
private store: Store<NiFiState>,
|
||||
private provenanceService: ProvenanceService,
|
||||
private errorHelper: ErrorHelper,
|
||||
private dialog: MatDialog,
|
||||
private router: Router
|
||||
) {}
|
||||
|
@ -58,10 +63,14 @@ export class ProvenanceEventListingEffects {
|
|||
response
|
||||
})
|
||||
),
|
||||
catchError((error) =>
|
||||
catchError(() =>
|
||||
of(
|
||||
ProvenanceEventListingActions.provenanceApiError({
|
||||
error: error.error
|
||||
ProvenanceEventListingActions.loadProvenanceOptionsSuccess({
|
||||
response: {
|
||||
provenanceOptions: {
|
||||
searchableFields: []
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
|
@ -74,38 +83,6 @@ export class ProvenanceEventListingEffects {
|
|||
this.actions$.pipe(
|
||||
ofType(ProvenanceEventListingActions.submitProvenanceQuery),
|
||||
map((action) => action.request),
|
||||
switchMap((request) =>
|
||||
from(this.provenanceService.submitProvenanceQuery(request)).pipe(
|
||||
map((response) =>
|
||||
ProvenanceEventListingActions.submitProvenanceQuerySuccess({
|
||||
response: {
|
||||
provenance: response.provenance
|
||||
}
|
||||
})
|
||||
),
|
||||
catchError((error) => {
|
||||
this.store.dispatch(
|
||||
ProvenanceEventListingActions.showOkDialog({
|
||||
title: 'Error',
|
||||
message: error.error
|
||||
})
|
||||
);
|
||||
|
||||
return of(
|
||||
ProvenanceEventListingActions.provenanceApiError({
|
||||
error: error.error
|
||||
})
|
||||
);
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
resubmitProvenanceQuery = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(ProvenanceEventListingActions.resubmitProvenanceQuery),
|
||||
map((action) => action.request),
|
||||
switchMap((request) => {
|
||||
const dialogReference = this.dialog.open(CancelDialog, {
|
||||
data: {
|
||||
|
@ -120,6 +97,37 @@ export class ProvenanceEventListingEffects {
|
|||
this.store.dispatch(ProvenanceEventListingActions.stopPollingProvenanceQuery());
|
||||
});
|
||||
|
||||
return from(this.provenanceService.submitProvenanceQuery(request)).pipe(
|
||||
map((response) =>
|
||||
ProvenanceEventListingActions.submitProvenanceQuerySuccess({
|
||||
response: {
|
||||
provenance: response.provenance
|
||||
}
|
||||
})
|
||||
),
|
||||
catchError((errorResponse: HttpErrorResponse) => {
|
||||
if (this.errorHelper.showErrorInContext(errorResponse.status)) {
|
||||
return of(
|
||||
ProvenanceEventListingActions.provenanceApiError({
|
||||
error: errorResponse.error
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.store.dispatch(ProvenanceEventListingActions.stopPollingProvenanceQuery());
|
||||
|
||||
return of(this.errorHelper.fullScreenError(errorResponse));
|
||||
}
|
||||
})
|
||||
);
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
resubmitProvenanceQuery = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(ProvenanceEventListingActions.resubmitProvenanceQuery),
|
||||
map((action) => action.request),
|
||||
switchMap((request) => {
|
||||
return of(ProvenanceEventListingActions.submitProvenanceQuery({ request }));
|
||||
})
|
||||
)
|
||||
|
@ -156,29 +164,34 @@ export class ProvenanceEventListingEffects {
|
|||
pollProvenanceQuery$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(ProvenanceEventListingActions.pollProvenanceQuery),
|
||||
concatLatestFrom(() => [this.store.select(selectProvenanceId), this.store.select(selectClusterNodeId)]),
|
||||
switchMap(([, id, clusterNodeId]) => {
|
||||
if (id) {
|
||||
return from(this.provenanceService.getProvenanceQuery(id, clusterNodeId)).pipe(
|
||||
map((response) =>
|
||||
ProvenanceEventListingActions.pollProvenanceQuerySuccess({
|
||||
response: {
|
||||
provenance: response.provenance
|
||||
}
|
||||
})
|
||||
),
|
||||
catchError((error) =>
|
||||
of(
|
||||
concatLatestFrom(() => [
|
||||
this.store.select(selectActiveProvenanceId).pipe(isDefinedAndNotNull()),
|
||||
this.store.select(selectClusterNodeId)
|
||||
]),
|
||||
switchMap(([, id, clusterNodeId]) =>
|
||||
from(this.provenanceService.getProvenanceQuery(id, clusterNodeId)).pipe(
|
||||
map((response) =>
|
||||
ProvenanceEventListingActions.pollProvenanceQuerySuccess({
|
||||
response: {
|
||||
provenance: response.provenance
|
||||
}
|
||||
})
|
||||
),
|
||||
catchError((errorResponse: HttpErrorResponse) => {
|
||||
if (this.errorHelper.showErrorInContext(errorResponse.status)) {
|
||||
return of(
|
||||
ProvenanceEventListingActions.provenanceApiError({
|
||||
error: error.error
|
||||
error: errorResponse.error
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return NEVER;
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.store.dispatch(ProvenanceEventListingActions.stopPollingProvenanceQuery());
|
||||
|
||||
return of(this.errorHelper.fullScreenError(errorResponse));
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -186,15 +199,8 @@ export class ProvenanceEventListingEffects {
|
|||
this.actions$.pipe(
|
||||
ofType(ProvenanceEventListingActions.pollProvenanceQuerySuccess),
|
||||
map((action) => action.response),
|
||||
switchMap((response) => {
|
||||
const query: Provenance = response.provenance;
|
||||
if (query.finished) {
|
||||
this.dialog.closeAll();
|
||||
return of(ProvenanceEventListingActions.stopPollingProvenanceQuery());
|
||||
} else {
|
||||
return NEVER;
|
||||
}
|
||||
})
|
||||
filter((response) => response.provenance.finished),
|
||||
switchMap(() => of(ProvenanceEventListingActions.stopPollingProvenanceQuery()))
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -205,18 +211,22 @@ export class ProvenanceEventListingEffects {
|
|||
)
|
||||
);
|
||||
|
||||
deleteProvenanceQuery$ = createEffect(
|
||||
() =>
|
||||
this.actions$.pipe(
|
||||
ofType(ProvenanceEventListingActions.deleteProvenanceQuery),
|
||||
concatLatestFrom(() => [this.store.select(selectProvenanceId), this.store.select(selectClusterNodeId)]),
|
||||
tap(([, id, clusterNodeId]) => {
|
||||
if (id) {
|
||||
this.provenanceService.deleteProvenanceQuery(id, clusterNodeId).subscribe();
|
||||
}
|
||||
})
|
||||
),
|
||||
{ dispatch: false }
|
||||
deleteProvenanceQuery$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(ProvenanceEventListingActions.deleteProvenanceQuery),
|
||||
concatLatestFrom(() => [
|
||||
this.store.select(selectActiveProvenanceId),
|
||||
this.store.select(selectClusterNodeId)
|
||||
]),
|
||||
tap(([, id, clusterNodeId]) => {
|
||||
this.dialog.closeAll();
|
||||
|
||||
if (id) {
|
||||
this.provenanceService.deleteProvenanceQuery(id, clusterNodeId).subscribe();
|
||||
}
|
||||
}),
|
||||
switchMap(() => of(ProvenanceEventListingActions.deleteProvenanceQuerySuccess()))
|
||||
)
|
||||
);
|
||||
|
||||
openSearchDialog$ = createEffect(
|
||||
|
@ -227,44 +237,40 @@ export class ProvenanceEventListingEffects {
|
|||
this.store.select(selectTimeOffset),
|
||||
this.store.select(selectProvenanceOptions),
|
||||
this.store.select(selectProvenanceRequest),
|
||||
this.store.select(selectAbout)
|
||||
this.store.select(selectAbout).pipe(isDefinedAndNotNull())
|
||||
]),
|
||||
tap(([, timeOffset, options, currentRequest, about]) => {
|
||||
if (about) {
|
||||
const dialogReference = this.dialog.open(ProvenanceSearchDialog, {
|
||||
data: {
|
||||
timeOffset,
|
||||
options,
|
||||
currentRequest
|
||||
},
|
||||
panelClass: 'large-dialog'
|
||||
});
|
||||
const dialogReference = this.dialog.open(ProvenanceSearchDialog, {
|
||||
data: {
|
||||
timeOffset,
|
||||
options,
|
||||
currentRequest
|
||||
},
|
||||
panelClass: 'large-dialog'
|
||||
});
|
||||
|
||||
dialogReference.componentInstance.timezone = about.timezone;
|
||||
dialogReference.componentInstance.timezone = about.timezone;
|
||||
|
||||
dialogReference.componentInstance.submitSearchCriteria
|
||||
.pipe(take(1))
|
||||
.subscribe((request: ProvenanceRequest) => {
|
||||
if (request.searchTerms) {
|
||||
const queryParams: any = {};
|
||||
if (request.searchTerms['ProcessorID']) {
|
||||
queryParams['componentId'] = request.searchTerms['ProcessorID'].value;
|
||||
}
|
||||
if (request.searchTerms['FlowFileUUID']) {
|
||||
queryParams['flowFileUuid'] = request.searchTerms['FlowFileUUID'].value;
|
||||
}
|
||||
|
||||
// if either of the supported query params are present in the query, update the url
|
||||
if (Object.keys(queryParams).length > 0) {
|
||||
this.router.navigate(['/provenance'], { queryParams });
|
||||
}
|
||||
dialogReference.componentInstance.submitSearchCriteria
|
||||
.pipe(take(1))
|
||||
.subscribe((request: ProvenanceRequest) => {
|
||||
if (request.searchTerms) {
|
||||
const queryParams: any = {};
|
||||
if (request.searchTerms['ProcessorID']) {
|
||||
queryParams['componentId'] = request.searchTerms['ProcessorID'].value;
|
||||
}
|
||||
if (request.searchTerms['FlowFileUUID']) {
|
||||
queryParams['flowFileUuid'] = request.searchTerms['FlowFileUUID'].value;
|
||||
}
|
||||
|
||||
this.store.dispatch(ProvenanceEventListingActions.saveProvenanceRequest({ request }));
|
||||
});
|
||||
}
|
||||
// if either of the supported query params are present in the query, update the url
|
||||
if (Object.keys(queryParams).length > 0) {
|
||||
this.router.navigate(['/provenance'], { queryParams });
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - if about hasn't loaded we should show an error
|
||||
this.store.dispatch(ProvenanceEventListingActions.saveProvenanceRequest({ request }));
|
||||
});
|
||||
})
|
||||
),
|
||||
{ dispatch: false }
|
||||
|
@ -311,18 +317,31 @@ export class ProvenanceEventListingEffects {
|
|||
dialogReference.componentInstance.replay
|
||||
.pipe(takeUntil(dialogReference.afterClosed()))
|
||||
.subscribe(() => {
|
||||
this.provenanceService.replay(request.id).subscribe(() => {
|
||||
this.store.dispatch(
|
||||
ProvenanceEventListingActions.showOkDialog({
|
||||
title: 'Provenance',
|
||||
message: 'Successfully submitted replay request.'
|
||||
})
|
||||
);
|
||||
dialogReference.close();
|
||||
|
||||
this.provenanceService.replay(request.id).subscribe({
|
||||
next: () => {
|
||||
this.store.dispatch(
|
||||
ProvenanceEventListingActions.showOkDialog({
|
||||
title: 'Provenance',
|
||||
message: 'Successfully submitted replay request.'
|
||||
})
|
||||
);
|
||||
},
|
||||
error: (errorResponse: HttpErrorResponse) => {
|
||||
this.store.dispatch(
|
||||
ErrorActions.snackBarError({ error: errorResponse.error })
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
error: () => {
|
||||
// TODO - handle error
|
||||
error: (errorResponse: HttpErrorResponse) => {
|
||||
if (this.errorHelper.showErrorInContext(errorResponse.status)) {
|
||||
this.store.dispatch(ErrorActions.snackBarError({ error: errorResponse.error }));
|
||||
} else {
|
||||
this.store.dispatch(this.errorHelper.fullScreenError(errorResponse));
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
@ -337,9 +356,14 @@ export class ProvenanceEventListingEffects {
|
|||
map((action) => action.request),
|
||||
tap((request) => {
|
||||
if (request.eventId) {
|
||||
this.provenanceService.getProvenanceEvent(request.eventId).subscribe((response) => {
|
||||
const event: any = response.provenanceEvent;
|
||||
this.router.navigate(this.getEventComponentLink(event.groupId, event.componentId));
|
||||
this.provenanceService.getProvenanceEvent(request.eventId).subscribe({
|
||||
next: (response) => {
|
||||
const event: any = response.provenanceEvent;
|
||||
this.router.navigate(this.getEventComponentLink(event.groupId, event.componentId));
|
||||
},
|
||||
error: (errorResponse: HttpErrorResponse) => {
|
||||
this.store.dispatch(ErrorActions.snackBarError({ error: errorResponse.error }));
|
||||
}
|
||||
});
|
||||
} else if (request.groupId && request.componentId) {
|
||||
this.router.navigate(this.getEventComponentLink(request.groupId, request.componentId));
|
||||
|
@ -349,6 +373,16 @@ export class ProvenanceEventListingEffects {
|
|||
{ dispatch: false }
|
||||
);
|
||||
|
||||
provenanceApiError$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(ProvenanceEventListingActions.provenanceApiError),
|
||||
tap(() => {
|
||||
this.store.dispatch(ProvenanceEventListingActions.stopPollingProvenanceQuery());
|
||||
}),
|
||||
switchMap(({ error }) => of(ErrorActions.addBannerError({ error })))
|
||||
)
|
||||
);
|
||||
|
||||
showOkDialog$ = createEffect(
|
||||
() =>
|
||||
this.actions$.pipe(
|
||||
|
|
|
@ -19,6 +19,7 @@ import { createReducer, on } from '@ngrx/store';
|
|||
import { ProvenanceEventListingState } from './index';
|
||||
import {
|
||||
clearProvenanceRequest,
|
||||
deleteProvenanceQuerySuccess,
|
||||
loadProvenanceOptionsSuccess,
|
||||
pollProvenanceQuerySuccess,
|
||||
provenanceApiError,
|
||||
|
@ -27,13 +28,35 @@ import {
|
|||
submitProvenanceQuery,
|
||||
submitProvenanceQuerySuccess
|
||||
} from './provenance-event-listing.actions';
|
||||
import { produce } from 'immer';
|
||||
|
||||
export const initialState: ProvenanceEventListingState = {
|
||||
options: null,
|
||||
request: null,
|
||||
provenance: null,
|
||||
loadedTimestamp: '',
|
||||
error: null,
|
||||
activeProvenance: null,
|
||||
completedProvenance: {
|
||||
id: '',
|
||||
uri: '',
|
||||
submissionTime: '',
|
||||
expiration: '',
|
||||
percentCompleted: 0,
|
||||
finished: false,
|
||||
request: {
|
||||
maxResults: 0,
|
||||
summarize: true,
|
||||
incrementalResults: false
|
||||
},
|
||||
results: {
|
||||
provenanceEvents: [],
|
||||
total: '',
|
||||
totalCount: 0,
|
||||
generated: 'N/A',
|
||||
oldestEvent: 'N/A',
|
||||
timeOffset: 0,
|
||||
errors: []
|
||||
}
|
||||
},
|
||||
loadedTimestamp: 'N/A',
|
||||
status: 'pending'
|
||||
};
|
||||
|
||||
|
@ -50,12 +73,22 @@ export const provenanceEventListingReducer = createReducer(
|
|||
...state,
|
||||
status: 'loading' as const
|
||||
})),
|
||||
on(submitProvenanceQuerySuccess, pollProvenanceQuerySuccess, (state, { response }) => ({
|
||||
on(submitProvenanceQuerySuccess, pollProvenanceQuerySuccess, (state, { response }) => {
|
||||
return produce(state, (draftState) => {
|
||||
const provenance = response.provenance;
|
||||
draftState.activeProvenance = provenance;
|
||||
|
||||
// if the query has finished save it as completed, the active query will be reset after deletion
|
||||
if (provenance.finished) {
|
||||
draftState.completedProvenance = provenance;
|
||||
draftState.loadedTimestamp = provenance.results.generated;
|
||||
draftState.status = 'success' as const;
|
||||
}
|
||||
});
|
||||
}),
|
||||
on(deleteProvenanceQuerySuccess, (state) => ({
|
||||
...state,
|
||||
provenance: response.provenance,
|
||||
loadedTimestamp: response.provenance.results.generated,
|
||||
error: null,
|
||||
status: 'success' as const
|
||||
activeProvenance: null
|
||||
})),
|
||||
on(saveProvenanceRequest, (state, { request }) => ({
|
||||
...state,
|
||||
|
@ -65,9 +98,8 @@ export const provenanceEventListingReducer = createReducer(
|
|||
...state,
|
||||
request: null
|
||||
})),
|
||||
on(provenanceApiError, (state, { error }) => ({
|
||||
on(provenanceApiError, (state) => ({
|
||||
...state,
|
||||
error,
|
||||
status: 'error' as const
|
||||
}))
|
||||
);
|
||||
|
|
|
@ -66,19 +66,27 @@ export const selectLoadedTimestamp = createSelector(
|
|||
(state: ProvenanceEventListingState) => state.loadedTimestamp
|
||||
);
|
||||
|
||||
export const selectProvenance = createSelector(
|
||||
export const selectActiveProvenance = createSelector(
|
||||
selectProvenanceEventListingState,
|
||||
(state: ProvenanceEventListingState) => state.provenance
|
||||
(state: ProvenanceEventListingState) => state.activeProvenance
|
||||
);
|
||||
|
||||
export const selectProvenanceId = createSelector(selectProvenance, (state: Provenance | null) => state?.id);
|
||||
export const selectCompletedProvenance = createSelector(
|
||||
selectProvenanceEventListingState,
|
||||
(state: ProvenanceEventListingState) => state.completedProvenance
|
||||
);
|
||||
|
||||
export const selectActiveProvenanceId = createSelector(selectActiveProvenance, (state: Provenance | null) => state?.id);
|
||||
|
||||
export const selectClusterNodeId = createSelector(
|
||||
selectProvenanceRequest,
|
||||
(state: ProvenanceRequest | null) => state?.clusterNodeId
|
||||
);
|
||||
|
||||
export const selectProvenanceResults = createSelector(selectProvenance, (state: Provenance | null) => state?.results);
|
||||
export const selectProvenanceResults = createSelector(
|
||||
selectCompletedProvenance,
|
||||
(state: Provenance | null) => state?.results
|
||||
);
|
||||
|
||||
export const selectTimeOffset = createSelector(
|
||||
selectProvenanceResults,
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
(resubmitProvenanceQuery)="resubmitProvenanceQuery()"
|
||||
(clearRequest)="clearRequest()"
|
||||
(queryLineage)="queryLineage($event)"
|
||||
(clearBannerErrors)="clearBannerErrors()"
|
||||
(resetLineage)="resetLineage()"></provenance-event-table>
|
||||
</ng-container>
|
||||
<ng-template #initialLoading>
|
||||
|
|
|
@ -27,7 +27,7 @@ import {
|
|||
} from '../../state/provenance-event-listing';
|
||||
import {
|
||||
selectLoadedTimestamp,
|
||||
selectProvenance,
|
||||
selectCompletedProvenance,
|
||||
selectProvenanceRequest,
|
||||
selectSearchableFieldsFromRoute,
|
||||
selectStatus
|
||||
|
@ -46,7 +46,8 @@ import {
|
|||
import { ProvenanceSearchDialog } from './provenance-search-dialog/provenance-search-dialog.component';
|
||||
import { resetLineage, submitLineageQuery } from '../../state/lineage/lineage.actions';
|
||||
import { LineageRequest } from '../../state/lineage';
|
||||
import { selectLineage } from '../../state/lineage/lineage.selectors';
|
||||
import { selectCompletedLineage } from '../../state/lineage/lineage.selectors';
|
||||
import { clearBannerErrors } from '../../../../state/error/error.actions';
|
||||
|
||||
@Component({
|
||||
selector: 'provenance-event-listing',
|
||||
|
@ -56,8 +57,8 @@ import { selectLineage } from '../../state/lineage/lineage.selectors';
|
|||
export class ProvenanceEventListing implements OnDestroy {
|
||||
status$ = this.store.select(selectStatus);
|
||||
loadedTimestamp$ = this.store.select(selectLoadedTimestamp);
|
||||
provenance$ = this.store.select(selectProvenance);
|
||||
lineage$ = this.store.select(selectLineage);
|
||||
provenance$ = this.store.select(selectCompletedProvenance);
|
||||
lineage$ = this.store.select(selectCompletedLineage);
|
||||
|
||||
request!: ProvenanceRequest;
|
||||
stateReset = false;
|
||||
|
@ -200,6 +201,10 @@ export class ProvenanceEventListing implements OnDestroy {
|
|||
);
|
||||
}
|
||||
|
||||
clearBannerErrors(): void {
|
||||
this.store.dispatch(clearBannerErrors());
|
||||
}
|
||||
|
||||
resetLineage(): void {
|
||||
this.store.dispatch(resetLineage());
|
||||
}
|
||||
|
@ -208,5 +213,6 @@ export class ProvenanceEventListing implements OnDestroy {
|
|||
this.stateReset = true;
|
||||
this.store.dispatch(resetProvenanceState());
|
||||
this.store.dispatch(resetLineage());
|
||||
this.store.dispatch(clearBannerErrors());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<div class="provenance-event-table h-full">
|
||||
<div class="provenance-event-table h-full flex flex-col gap-y-2">
|
||||
<error-banner></error-banner>
|
||||
<div [class.hidden]="showLineage" class="h-full flex flex-col gap-y-2">
|
||||
<div class="flex flex-col">
|
||||
<div [class.invisible]="!filterApplied" class="value font-bold">
|
||||
|
|
|
@ -19,15 +19,30 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
|
||||
import { ProvenanceEventTable } from './provenance-event-table.component';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../../state/error/error.reducer';
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
describe('ProvenanceEventTable', () => {
|
||||
let component: ProvenanceEventTable;
|
||||
let fixture: ComponentFixture<ProvenanceEventTable>;
|
||||
|
||||
@Component({
|
||||
selector: 'error-banner',
|
||||
standalone: true,
|
||||
template: ''
|
||||
})
|
||||
class MockErrorBanner {}
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ProvenanceEventTable, MatTableModule, BrowserAnimationsModule]
|
||||
imports: [ProvenanceEventTable, MockErrorBanner, MatTableModule, NoopAnimationsModule],
|
||||
providers: [
|
||||
provideMockStore({
|
||||
initialState
|
||||
})
|
||||
]
|
||||
});
|
||||
fixture = TestBed.createComponent(ProvenanceEventTable);
|
||||
component = fixture.componentInstance;
|
||||
|
|
|
@ -38,6 +38,7 @@ import { LineageComponent } from './lineage/lineage.component';
|
|||
import { GoToProvenanceEventSourceRequest, ProvenanceEventRequest } from '../../../state/provenance-event-listing';
|
||||
import { MatSliderModule } from '@angular/material/slider';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { ErrorBanner } from '../../../../../ui/common/error-banner/error-banner.component';
|
||||
|
||||
@Component({
|
||||
selector: 'provenance-event-table',
|
||||
|
@ -58,7 +59,8 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|||
AsyncPipe,
|
||||
MatPaginatorModule,
|
||||
LineageComponent,
|
||||
MatSliderModule
|
||||
MatSliderModule,
|
||||
ErrorBanner
|
||||
],
|
||||
styleUrls: ['./provenance-event-table.component.scss']
|
||||
})
|
||||
|
@ -149,6 +151,7 @@ export class ProvenanceEventTable implements AfterViewInit {
|
|||
@Output() resubmitProvenanceQuery: EventEmitter<void> = new EventEmitter<void>();
|
||||
@Output() queryLineage: EventEmitter<LineageRequest> = new EventEmitter<LineageRequest>();
|
||||
@Output() resetLineage: EventEmitter<void> = new EventEmitter<void>();
|
||||
@Output() clearBannerErrors: EventEmitter<void> = new EventEmitter<void>();
|
||||
|
||||
protected readonly TextTip = TextTip;
|
||||
protected readonly BulletinsTip = BulletinsTip;
|
||||
|
@ -305,11 +308,7 @@ export class ProvenanceEventTable implements AfterViewInit {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (event.componentId === 'Remote Output Port' || event.componentId === 'Remote Input Port') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !(event.componentId === 'Remote Output Port' || event.componentId === 'Remote Input Port');
|
||||
}
|
||||
|
||||
goToClicked(event: ProvenanceEventSummary): void {
|
||||
|
@ -327,6 +326,8 @@ export class ProvenanceEventTable implements AfterViewInit {
|
|||
this.eventId = event.id;
|
||||
this.showLineage = true;
|
||||
|
||||
this.clearBannerErrors.next();
|
||||
|
||||
this.submitLineageQuery({
|
||||
lineageRequestType: 'FLOWFILE',
|
||||
uuid: event.flowFileUuid,
|
||||
|
@ -345,6 +346,7 @@ export class ProvenanceEventTable implements AfterViewInit {
|
|||
this.eventTimestampStep = 1;
|
||||
this.initialEventTimestampThreshold = 0;
|
||||
this.currentEventTimestampThreshold = 0;
|
||||
this.clearBannerErrors.next();
|
||||
this.resetLineage.next();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="request.options.searchableFields.length === 0">
|
||||
<div class="unset mb-5">
|
||||
No searchable fields are available. Search criteria based on date, time, and file size still available.
|
||||
</div>
|
||||
</ng-container>
|
||||
<mat-form-field>
|
||||
<mat-label>Date Range</mat-label>
|
||||
<mat-date-range-input [rangePicker]="picker">
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
.search-events-form {
|
||||
@include mat.button-density(-1);
|
||||
|
||||
mat-dialog-content {
|
||||
min-height: 450px;
|
||||
}
|
||||
|
||||
.mat-mdc-form-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
|
||||
import { ProvenanceSearchDialog } from './provenance-search-dialog.component';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { MatNativeDateModule } from '@angular/material/core';
|
||||
|
||||
describe('ProvenanceSearchDialog', () => {
|
||||
|
@ -71,7 +71,7 @@ describe('ProvenanceSearchDialog', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ProvenanceSearchDialog, BrowserAnimationsModule, MatNativeDateModule],
|
||||
imports: [ProvenanceSearchDialog, NoopAnimationsModule, MatNativeDateModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }]
|
||||
});
|
||||
fixture = TestBed.createComponent(ProvenanceSearchDialog);
|
||||
|
|
|
@ -102,7 +102,7 @@ export interface FlowFileDialogRequest {
|
|||
|
||||
export interface QueueListingState {
|
||||
activeListingRequest: ListingRequest | null;
|
||||
completedListingRequest: ListingRequest | null;
|
||||
completedListingRequest: ListingRequest;
|
||||
connectionLabel: string;
|
||||
loadedTimestamp: string;
|
||||
status: 'pending' | 'loading' | 'error' | 'success';
|
||||
|
|
|
@ -66,13 +66,13 @@ export const queueListingReducer = createReducer(
|
|||
on(submitQueueListingRequestSuccess, pollQueueListingRequestSuccess, (state, { response }) => {
|
||||
return produce(state, (draftState) => {
|
||||
const listingRequest = response.requestEntity.listingRequest;
|
||||
draftState.activeListingRequest = listingRequest;
|
||||
|
||||
// if the query has finished save it as completed, the active query will be reset after deletion
|
||||
if (listingRequest.finished) {
|
||||
draftState.completedListingRequest = listingRequest;
|
||||
draftState.loadedTimestamp = listingRequest.lastUpdated;
|
||||
draftState.status = 'success' as const;
|
||||
} else {
|
||||
draftState.activeListingRequest = listingRequest;
|
||||
}
|
||||
});
|
||||
}),
|
||||
|
|
|
@ -19,7 +19,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
|
||||
import { FlowFileDialog } from './flowfile-dialog.component';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { FlowFileDialogRequest } from '../../../state/queue-listing';
|
||||
|
||||
describe('FlowFileDialog', () => {
|
||||
|
@ -46,7 +46,7 @@ describe('FlowFileDialog', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [FlowFileDialog, BrowserAnimationsModule],
|
||||
imports: [FlowFileDialog, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }]
|
||||
});
|
||||
fixture = TestBed.createComponent(FlowFileDialog);
|
||||
|
|
|
@ -19,7 +19,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
|
||||
import { FlowFileTable } from './flowfile-table.component';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { Component } from '@angular/core';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../../state/error/error.reducer';
|
||||
|
@ -37,7 +37,7 @@ describe('FlowFileTable', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [FlowFileTable, MockErrorBanner, MatTableModule, BrowserAnimationsModule],
|
||||
imports: [FlowFileTable, MockErrorBanner, MatTableModule, NoopAnimationsModule],
|
||||
providers: [
|
||||
provideMockStore({
|
||||
initialState
|
||||
|
|
|
@ -627,7 +627,9 @@ export class ParameterProvidersEffects {
|
|||
concatLatestFrom(() => this.store.select(selectApplyParameterProviderParametersRequest)),
|
||||
tap(([, updateRequest]) => {
|
||||
if (updateRequest) {
|
||||
this.parameterProviderService.deleteParameterProviderParametersUpdateRequest(updateRequest);
|
||||
this.parameterProviderService
|
||||
.deleteParameterProviderParametersUpdateRequest(updateRequest)
|
||||
.subscribe();
|
||||
}
|
||||
})
|
||||
),
|
||||
|
|
|
@ -21,7 +21,7 @@ import { CreateFlowAnalysisRule } from './create-flow-analysis-rule.component';
|
|||
import { CreateFlowAnalysisRuleDialogRequest } from '../../../state/flow-analysis-rules';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { initialState } from '../../../state/flow-analysis-rules/flow-analysis-rules.reducer';
|
||||
|
||||
describe('CreateFlowAnalysisRule', () => {
|
||||
|
@ -47,7 +47,7 @@ describe('CreateFlowAnalysisRule', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CreateFlowAnalysisRule, BrowserAnimationsModule],
|
||||
imports: [CreateFlowAnalysisRule, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }, provideMockStore({ initialState })]
|
||||
});
|
||||
fixture = TestBed.createComponent(CreateFlowAnalysisRule);
|
||||
|
|
|
@ -19,7 +19,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
|
||||
import { EditFlowAnalysisRule } from './edit-flow-analysis-rule.component';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { EditFlowAnalysisRuleDialogRequest } from '../../../state/flow-analysis-rules';
|
||||
import { Component } from '@angular/core';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
|
@ -101,7 +101,7 @@ describe('EditFlowAnalysisRule', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [EditFlowAnalysisRule, MockErrorBanner, BrowserAnimationsModule],
|
||||
imports: [EditFlowAnalysisRule, MockErrorBanner, NoopAnimationsModule],
|
||||
providers: [
|
||||
{ provide: MAT_DIALOG_DATA, useValue: data },
|
||||
provideMockStore({
|
||||
|
|
|
@ -19,7 +19,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
|
||||
import { FlowAnalysisRuleTable } from './flow-analysis-rule-table.component';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('FlowAnalysisRuleTable', () => {
|
||||
let component: FlowAnalysisRuleTable;
|
||||
|
@ -27,7 +27,7 @@ describe('FlowAnalysisRuleTable', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [BrowserAnimationsModule, MatTableModule, FlowAnalysisRuleTable]
|
||||
imports: [NoopAnimationsModule, MatTableModule, FlowAnalysisRuleTable]
|
||||
});
|
||||
fixture = TestBed.createComponent(FlowAnalysisRuleTable);
|
||||
component = fixture.componentInstance;
|
||||
|
|
|
@ -23,7 +23,7 @@ import { initialState } from '../../../state/general/general.reducer';
|
|||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('GeneralForm', () => {
|
||||
let component: GeneralForm;
|
||||
|
@ -32,7 +32,7 @@ describe('GeneralForm', () => {
|
|||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [GeneralForm],
|
||||
imports: [BrowserAnimationsModule, MatFormFieldModule, MatInputModule, FormsModule, ReactiveFormsModule],
|
||||
imports: [NoopAnimationsModule, MatFormFieldModule, MatInputModule, FormsModule, ReactiveFormsModule],
|
||||
providers: [
|
||||
provideMockStore({
|
||||
initialState
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { CreateRegistryClient } from './create-registry-client.component';
|
||||
import { CreateRegistryClientDialogRequest } from '../../../state/registry-clients';
|
||||
|
||||
|
@ -43,7 +43,7 @@ describe('CreateRegistryClient', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CreateRegistryClient, BrowserAnimationsModule],
|
||||
imports: [CreateRegistryClient, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }]
|
||||
});
|
||||
fixture = TestBed.createComponent(CreateRegistryClient);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { EditRegistryClient } from './edit-registry-client.component';
|
||||
import { EditRegistryClientDialogRequest } from '../../../state/registry-clients';
|
||||
import { Component } from '@angular/core';
|
||||
|
@ -114,7 +114,7 @@ describe('EditRegistryClient', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [EditRegistryClient, MockErrorBanner, BrowserAnimationsModule],
|
||||
imports: [EditRegistryClient, MockErrorBanner, NoopAnimationsModule],
|
||||
providers: [
|
||||
{ provide: MAT_DIALOG_DATA, useValue: data },
|
||||
provideMockStore({
|
||||
|
|
|
@ -20,7 +20,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
import { RegistryClientTable } from './registry-client-table.component';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { MatSortModule } from '@angular/material/sort';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('RegistryClientTable', () => {
|
||||
let component: RegistryClientTable;
|
||||
|
@ -29,7 +29,7 @@ describe('RegistryClientTable', () => {
|
|||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [RegistryClientTable],
|
||||
imports: [MatTableModule, MatSortModule, BrowserAnimationsModule]
|
||||
imports: [MatTableModule, MatSortModule, NoopAnimationsModule]
|
||||
});
|
||||
fixture = TestBed.createComponent(RegistryClientTable);
|
||||
component = fixture.componentInstance;
|
||||
|
|
|
@ -22,7 +22,7 @@ import { CreateReportingTaskDialogRequest } from '../../../state/reporting-tasks
|
|||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../../state/extension-types/extension-types.reducer';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('CreateReportingTask', () => {
|
||||
let component: CreateReportingTask;
|
||||
|
@ -46,7 +46,7 @@ describe('CreateReportingTask', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CreateReportingTask, BrowserAnimationsModule],
|
||||
imports: [CreateReportingTask, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }, provideMockStore({ initialState })]
|
||||
});
|
||||
fixture = TestBed.createComponent(CreateReportingTask);
|
||||
|
|
|
@ -19,7 +19,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
|
||||
import { EditReportingTask } from './edit-reporting-task.component';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { EditReportingTaskDialogRequest } from '../../../state/reporting-tasks';
|
||||
import { Component } from '@angular/core';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
|
@ -394,7 +394,7 @@ describe('EditReportingTask', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [EditReportingTask, MockErrorBanner, BrowserAnimationsModule],
|
||||
imports: [EditReportingTask, MockErrorBanner, NoopAnimationsModule],
|
||||
providers: [
|
||||
{ provide: MAT_DIALOG_DATA, useValue: data },
|
||||
provideMockStore({
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UserAccessPolicies } from './user-access-policies.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { UserAccessPoliciesDialogRequest } from '../../../state/user-listing';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
|
||||
|
@ -52,7 +52,7 @@ describe('UserAccessPolicies', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [UserAccessPolicies, BrowserAnimationsModule],
|
||||
imports: [UserAccessPolicies, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }]
|
||||
});
|
||||
fixture = TestBed.createComponent(UserAccessPolicies);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ComponentStateDialog } from './component-state.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../state/component-state/component-state.reducer';
|
||||
|
||||
|
@ -28,7 +28,7 @@ describe('ComponentStateDialog', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ComponentStateDialog, BrowserAnimationsModule],
|
||||
imports: [ComponentStateDialog, NoopAnimationsModule],
|
||||
providers: [provideMockStore({ initialState })]
|
||||
});
|
||||
fixture = TestBed.createComponent(ComponentStateDialog);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ControllerServiceTable } from './controller-service-table.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('ControllerServiceTable', () => {
|
||||
let component: ControllerServiceTable;
|
||||
|
@ -26,7 +26,7 @@ describe('ControllerServiceTable', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [BrowserAnimationsModule, ControllerServiceTable]
|
||||
imports: [NoopAnimationsModule, ControllerServiceTable]
|
||||
});
|
||||
fixture = TestBed.createComponent(ControllerServiceTable);
|
||||
component = fixture.componentInstance;
|
||||
|
|
|
@ -21,7 +21,7 @@ import { CreateControllerService } from './create-controller-service.component';
|
|||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../state/extension-types/extension-types.reducer';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { CreateControllerServiceDialogRequest } from '../../../../state/shared';
|
||||
|
||||
describe('CreateControllerService', () => {
|
||||
|
@ -56,7 +56,7 @@ describe('CreateControllerService', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CreateControllerService, BrowserAnimationsModule],
|
||||
imports: [CreateControllerService, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }, provideMockStore({ initialState })]
|
||||
});
|
||||
fixture = TestBed.createComponent(CreateControllerService);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DisableControllerService } from './disable-controller-service.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../state/contoller-service-state/controller-service-state.reducer';
|
||||
import { ComponentType, SetEnableControllerServiceDialogRequest } from '../../../../state/shared';
|
||||
|
@ -341,7 +341,7 @@ describe('EnableControllerService', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [DisableControllerService, BrowserAnimationsModule],
|
||||
imports: [DisableControllerService, NoopAnimationsModule],
|
||||
providers: [provideMockStore({ initialState }), { provide: MAT_DIALOG_DATA, useValue: data }]
|
||||
});
|
||||
fixture = TestBed.createComponent(DisableControllerService);
|
||||
|
|
|
@ -20,7 +20,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
import { EditControllerService } from './edit-controller-service.component';
|
||||
import { EditControllerServiceDialogRequest } from '../../../../state/shared';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { Component } from '@angular/core';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../state/error/error.reducer';
|
||||
|
@ -553,7 +553,7 @@ describe('EditControllerService', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [EditControllerService, MockErrorBanner, BrowserAnimationsModule],
|
||||
imports: [EditControllerService, MockErrorBanner, NoopAnimationsModule],
|
||||
providers: [
|
||||
{ provide: MAT_DIALOG_DATA, useValue: data },
|
||||
provideMockStore({
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { EnableControllerService } from './enable-controller-service.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../../state/contoller-service-state/controller-service-state.reducer';
|
||||
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
||||
|
@ -341,7 +341,7 @@ describe('EnableControllerService', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [EnableControllerService, BrowserAnimationsModule, MatDialogModule],
|
||||
imports: [EnableControllerService, NoopAnimationsModule, MatDialogModule],
|
||||
providers: [provideMockStore({ initialState }), { provide: MAT_DIALOG_DATA, useValue: data }]
|
||||
});
|
||||
fixture = TestBed.createComponent(EnableControllerService);
|
||||
|
|
|
@ -20,7 +20,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
import { EditParameterDialog } from './edit-parameter-dialog.component';
|
||||
import { EditParameterRequest } from '../../../state/shared';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('EditParameterDialog', () => {
|
||||
let component: EditParameterDialog;
|
||||
|
@ -51,7 +51,7 @@ describe('EditParameterDialog', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [EditParameterDialog, BrowserAnimationsModule],
|
||||
imports: [EditParameterDialog, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }]
|
||||
});
|
||||
fixture = TestBed.createComponent(EditParameterDialog);
|
||||
|
|
|
@ -20,7 +20,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
import { EditTenantDialog } from './edit-tenant-dialog.component';
|
||||
import { EditTenantRequest } from '../../../state/shared';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { Component } from '@angular/core';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { initialState } from '../../../state/error/error.reducer';
|
||||
|
@ -794,7 +794,7 @@ describe('EditTenantDialog', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [EditTenantDialog, MockErrorBanner, BrowserAnimationsModule],
|
||||
imports: [EditTenantDialog, MockErrorBanner, NoopAnimationsModule],
|
||||
providers: [
|
||||
{ provide: MAT_DIALOG_DATA, useValue: data },
|
||||
provideMockStore({
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ExtensionCreation } from './extension-creation.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('ExtensionCreation', () => {
|
||||
let component: ExtensionCreation;
|
||||
|
@ -26,7 +26,7 @@ describe('ExtensionCreation', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ExtensionCreation, BrowserAnimationsModule]
|
||||
imports: [ExtensionCreation, NoopAnimationsModule]
|
||||
});
|
||||
fixture = TestBed.createComponent(ExtensionCreation);
|
||||
component = fixture.componentInstance;
|
||||
|
|
|
@ -21,7 +21,7 @@ import { NewPropertyDialog } from './new-property-dialog.component';
|
|||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { NewPropertyDialogRequest } from '../../../state/shared';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('NewPropertyDialog', () => {
|
||||
let component: NewPropertyDialog;
|
||||
|
@ -34,7 +34,7 @@ describe('NewPropertyDialog', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [NewPropertyDialog, BrowserAnimationsModule, FormsModule, ReactiveFormsModule],
|
||||
imports: [NewPropertyDialog, NoopAnimationsModule, FormsModule, ReactiveFormsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }]
|
||||
});
|
||||
fixture = TestBed.createComponent(NewPropertyDialog);
|
||||
|
|
|
@ -21,7 +21,7 @@ import { ComboEditor } from './combo-editor.component';
|
|||
import { PropertyItem } from '../../property-table.component';
|
||||
import { Parameter } from '../../../../../state/shared';
|
||||
import { of } from 'rxjs';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('ComboEditor', () => {
|
||||
let component: ComboEditor;
|
||||
|
@ -73,7 +73,7 @@ describe('ComboEditor', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ComboEditor, BrowserAnimationsModule]
|
||||
imports: [ComboEditor, NoopAnimationsModule]
|
||||
});
|
||||
fixture = TestBed.createComponent(ComboEditor);
|
||||
component = fixture.componentInstance;
|
||||
|
|
|
@ -399,11 +399,7 @@
|
|||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
color="primary"
|
||||
mat-stroked-button
|
||||
mat-dialog-close
|
||||
(click)="replayClicked()">
|
||||
<button color="primary" mat-stroked-button (click)="replayClicked()">
|
||||
<i class="fa fa-repeat"></i>
|
||||
Replay
|
||||
</button>
|
||||
|
|
|
@ -19,7 +19,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
|
||||
import { ProvenanceEventDialog } from './provenance-event-dialog.component';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('ProvenanceEventDialog', () => {
|
||||
let component: ProvenanceEventDialog;
|
||||
|
@ -71,7 +71,7 @@ describe('ProvenanceEventDialog', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ProvenanceEventDialog, BrowserAnimationsModule],
|
||||
imports: [ProvenanceEventDialog, NoopAnimationsModule],
|
||||
providers: [{ provide: MAT_DIALOG_DATA, useValue: data }]
|
||||
});
|
||||
fixture = TestBed.createComponent(ProvenanceEventDialog);
|
||||
|
|
Loading…
Reference in New Issue