diff --git a/frontend/src/app/diagram/diagram.component.html b/frontend/src/app/diagram/diagram.component.html index e6594ae99e..32ed00a471 100644 --- a/frontend/src/app/diagram/diagram.component.html +++ b/frontend/src/app/diagram/diagram.component.html @@ -1,6 +1,9 @@ -
+
-
+

Kein Alignment vorhanden

diff --git a/frontend/src/app/diagram/diagram.component.spec.ts b/frontend/src/app/diagram/diagram.component.spec.ts index 2a9d737409..01b91edda8 100644 --- a/frontend/src/app/diagram/diagram.component.spec.ts +++ b/frontend/src/app/diagram/diagram.component.spec.ts @@ -44,7 +44,7 @@ describe('DiagramComponent', () => { component.prepareDiagramData(alignmentLists); expect(component.generateNodes).toHaveBeenCalled(); - expect(component.noAlignmentData).toBeFalsy(); + expect(component.alignmentDataCache?.alignmentObjectDtoList.length).not.toEqual(0); }); it('should not call generateElements if alignmentData is empty', () => { @@ -57,7 +57,7 @@ describe('DiagramComponent', () => { component.prepareDiagramData(alignmentLists); expect(component.generateNodes).not.toHaveBeenCalled(); - expect(component.noAlignmentData).toBeTruthy(); + expect(component.alignmentDataCache?.alignmentObjectDtoList.length).toEqual(0); }); it('should call prepareDiagramData when Subject receives new data', () => { diff --git a/frontend/src/app/diagram/diagram.component.ts b/frontend/src/app/diagram/diagram.component.ts index 1fa6bc43d7..4496be2564 100644 --- a/frontend/src/app/diagram/diagram.component.ts +++ b/frontend/src/app/diagram/diagram.component.ts @@ -19,6 +19,9 @@ import { KeyResultOrdinal } from '../shared/types/model/KeyResultOrdinal'; import { Router } from '@angular/router'; import { AlignmentObject } from '../shared/types/model/AlignmentObject'; import { AlignmentConnection } from '../shared/types/model/AlignmentConnection'; +import { Zone } from '../shared/types/enums/Zone'; +import { ObjectiveState } from '../shared/types/enums/ObjectiveState'; +import { RefreshDataService } from '../shared/services/refresh-data.service'; @Component({ selector: 'app-diagram', @@ -29,11 +32,11 @@ export class DiagramComponent implements AfterViewInit, OnDestroy { private alignmentData$: Subject = new Subject(); cy!: cytoscape.Core; diagramData: any[] = []; - noAlignmentData: boolean = false; alignmentDataCache: AlignmentLists | null = null; constructor( private keyResultService: KeyresultService, + private refreshDataService: RefreshDataService, private router: Router, ) {} @@ -47,11 +50,15 @@ export class DiagramComponent implements AfterViewInit, OnDestroy { } ngAfterViewInit(): void { + this.refreshDataService.reloadOverviewSubject.subscribe((value) => { + console.log('reload this kuchen'); + console.log(value); + }); this.alignmentData.subscribe((alignmentData: AlignmentLists): void => { let lastAlignmentItem: AlignmentObject = alignmentData.alignmentObjectDtoList[alignmentData.alignmentObjectDtoList.length - 1]; - let diagramReloadRequired: boolean = + const diagramReloadRequired: boolean = lastAlignmentItem?.objectTitle === 'reload' ? lastAlignmentItem?.objectType === 'true' : JSON.stringify(this.alignmentDataCache) !== JSON.stringify(alignmentData); @@ -70,6 +77,7 @@ export class DiagramComponent implements AfterViewInit, OnDestroy { ngOnDestroy(): void { this.cleanUpDiagram(); + this.alignmentData.unsubscribe(); } generateDiagram(): void { @@ -140,10 +148,7 @@ export class DiagramComponent implements AfterViewInit, OnDestroy { } prepareDiagramData(alignmentData: AlignmentLists): void { - if (alignmentData.alignmentObjectDtoList.length == 0) { - this.noAlignmentData = true; - } else { - this.noAlignmentData = false; + if (alignmentData.alignmentObjectDtoList.length != 0) { this.generateNodes(alignmentData); } } @@ -248,11 +253,11 @@ export class DiagramComponent implements AfterViewInit, OnDestroy { generateObjectiveSVG(title: string, teamName: string, state: string): string { switch (state) { - case 'ONGOING': + case ObjectiveState.ONGOING: return generateObjectiveSVG(title, teamName, getOnGoingIcon); - case 'SUCCESSFUL': + case ObjectiveState.SUCCESSFUL: return generateObjectiveSVG(title, teamName, getSuccessfulIcon); - case 'NOTSUCCESSFUL': + case ObjectiveState.NOTSUCCESSFUL: return generateObjectiveSVG(title, teamName, getNotSuccessfulIcon); default: return generateObjectiveSVG(title, teamName, getDraftIcon); @@ -261,13 +266,13 @@ export class DiagramComponent implements AfterViewInit, OnDestroy { generateKeyResultSVG(title: string, teamName: string, state: string | undefined): string { switch (state) { - case 'FAIL': + case Zone.FAIL: return generateKeyResultSVG(title, teamName, '#BA3838', 'white'); - case 'COMMIT': + case Zone.COMMIT: return generateKeyResultSVG(title, teamName, '#FFD600', 'black'); - case 'TARGET': + case Zone.TARGET: return generateKeyResultSVG(title, teamName, '#1E8A29', 'black'); - case 'STRETCH': + case Zone.STRETCH: return generateKeyResultSVG(title, teamName, '#1E5A96', 'white'); default: return generateNeutralKeyResultSVG(title, teamName); diff --git a/frontend/src/app/objective-detail/objective-detail.component.ts b/frontend/src/app/objective-detail/objective-detail.component.ts index 03bd8735e3..747bd70ea0 100644 --- a/frontend/src/app/objective-detail/objective-detail.component.ts +++ b/frontend/src/app/objective-detail/objective-detail.component.ts @@ -65,11 +65,9 @@ export class ObjectiveDetailComponent { .subscribe((result) => { if (result?.openNew) { this.openAddKeyResultDialog(); - } else if (result == '' || result == undefined) { return; - } else { - this.refreshDataService.markDataRefresh(); } + this.refreshDataService.markDataRefresh(); }); } diff --git a/frontend/src/app/overview/overview.component.spec.ts b/frontend/src/app/overview/overview.component.spec.ts index e38f09d652..c047057d24 100644 --- a/frontend/src/app/overview/overview.component.spec.ts +++ b/frontend/src/app/overview/overview.component.spec.ts @@ -2,7 +2,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { OverviewComponent } from './overview.component'; import { HttpClientTestingModule } from '@angular/common/http/testing'; -import { overViewEntity1 } from '../shared/testData'; +import { alignmentLists, overViewEntity1 } from '../shared/testData'; import { BehaviorSubject, of, Subject } from 'rxjs'; import { OverviewService } from '../shared/services/overview.service'; import { AppRoutingModule } from '../app-routing.module'; @@ -16,11 +16,16 @@ import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { MatIconModule } from '@angular/material/icon'; import { MatMenuModule } from '@angular/material/menu'; import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { AlignmentService } from '../shared/services/alignment.service'; const overviewService = { getOverview: jest.fn(), }; +const alignmentService = { + getAlignmentByFilter: jest.fn(), +}; + const authGuardMock = () => { return Promise.resolve(true); }; @@ -53,6 +58,10 @@ describe('OverviewComponent', () => { provide: OverviewService, useValue: overviewService, }, + { + provide: AlignmentService, + useValue: alignmentService, + }, { provide: authGuard, useValue: authGuardMock, @@ -132,6 +141,23 @@ describe('OverviewComponent', () => { expect(component.loadOverview).toHaveBeenLastCalledWith(); }); + it('should call overviewService on overview', async () => { + jest.spyOn(overviewService, 'getOverview'); + component.isOverview = true; + + component.loadOverview(3, [5, 6], '', null); + expect(overviewService.getOverview).toHaveBeenCalled(); + }); + + it('should call alignmentService on diagram', async () => { + jest.spyOn(alignmentService, 'getAlignmentByFilter').mockReturnValue(of(alignmentLists)); + component.isOverview = false; + fixture.detectChanges(); + + component.loadOverview(3, [5, 6], '', null); + expect(alignmentService.getAlignmentByFilter).toHaveBeenCalled(); + }); + function markFiltersAsReady() { refreshDataServiceMock.quarterFilterReady.next(null); refreshDataServiceMock.teamFilterReady.next(null); diff --git a/frontend/src/app/overview/overview.component.ts b/frontend/src/app/overview/overview.component.ts index 25ac21ff80..cc97822235 100644 --- a/frontend/src/app/overview/overview.component.ts +++ b/frontend/src/app/overview/overview.component.ts @@ -69,45 +69,53 @@ export class OverviewComponent implements OnInit, OnDestroy { this.loadOverview(quarterId, teamIds, objectiveQueryString, reload); } - loadOverview(quarterId?: number, teamIds?: number[], objectiveQuery?: string, reload?: boolean | null) { + loadOverview(quarterId?: number, teamIds?: number[], objectiveQuery?: string, reload?: boolean | null): void { if (this.isOverview) { - this.overviewService - .getOverview(quarterId, teamIds, objectiveQuery) - .pipe( - catchError(() => { - this.loadOverview(); - return EMPTY; - }), - ) - .subscribe((dashboard) => { - this.hasAdminAccess.next(dashboard.adminAccess); - this.overviewEntities$.next(dashboard.overviews); - }); + this.loadOverviewData(quarterId, teamIds, objectiveQuery); } else { - this.alignmentService - .getAlignmentByFilter(quarterId, teamIds, objectiveQuery) - .pipe( - catchError(() => { - this.loadOverview(); - return EMPTY; - }), - ) - .subscribe((alignmentLists: AlignmentLists) => { - if (reload != null) { - let alignmentObjectReload: AlignmentObject = { - objectId: 0, - objectTitle: 'reload', - objectType: reload.toString(), - objectTeamName: '', - objectState: null, - }; - alignmentLists.alignmentObjectDtoList.push(alignmentObjectReload); - } - this.alignmentLists$.next(alignmentLists); - }); + this.loadAlignmentData(quarterId, teamIds, objectiveQuery, reload); } } + loadOverviewData(quarterId?: number, teamIds?: number[], objectiveQuery?: string): void { + this.overviewService + .getOverview(quarterId, teamIds, objectiveQuery) + .pipe( + catchError(() => { + this.loadOverview(); + return EMPTY; + }), + ) + .subscribe((dashboard) => { + this.hasAdminAccess.next(dashboard.adminAccess); + this.overviewEntities$.next(dashboard.overviews); + }); + } + + loadAlignmentData(quarterId?: number, teamIds?: number[], objectiveQuery?: string, reload?: boolean | null): void { + this.alignmentService + .getAlignmentByFilter(quarterId, teamIds, objectiveQuery) + .pipe( + catchError(() => { + this.loadOverview(); + return EMPTY; + }), + ) + .subscribe((alignmentLists: AlignmentLists) => { + if (reload != null) { + let alignmentObjectReload: AlignmentObject = { + objectId: 0, + objectTitle: 'reload', + objectType: reload.toString(), + objectTeamName: '', + objectState: null, + }; + alignmentLists.alignmentObjectDtoList.push(alignmentObjectReload); + } + this.alignmentLists$.next(alignmentLists); + }); + } + ngOnDestroy(): void { this.destroyed$.next(true); this.destroyed$.complete(); diff --git a/frontend/src/app/shared/types/enums/ObjectiveState.ts b/frontend/src/app/shared/types/enums/ObjectiveState.ts new file mode 100644 index 0000000000..342fa5a49d --- /dev/null +++ b/frontend/src/app/shared/types/enums/ObjectiveState.ts @@ -0,0 +1,6 @@ +export enum ObjectiveState { + DRAFT = 'DRAFT', + ONGOING = 'ONGOING', + SUCCESSFUL = 'SUCCESSFUL', + NOTSUCCESSFUL = 'NOTSUCCESSFUL', +}