Skip to content

Commit

Permalink
Get current quarter from backend (#1039)
Browse files Browse the repository at this point in the history
* add auto data-migration

* jar is now debuggable

* add jar debug dev tools only on profile

* change log levels

* try to fix autorestart of spring

* complete auto restart of container

* rename intelij config and change log level of spring to debug in staging config

* rename folder

* update docker compose file

* use external profile to disable formatter

* clean up

* add jar debug dev tools only on profile

* add api endpoint

* use api to get current quarter

* convert quarter to a class instead of an interface

* use class syntax

* update specs to use the class syntax for quarters

* mock new class function in test

* add integratin test for current quarter endpoint

* fix default quarter for new objective selection

* use v2 for quarter url and update tests accoridingly

* change merhod to fakeAsync

* try to override provider mid test

* Dispatch change instead of input event in onSubmit create test and get element by test id instead of id

* Remove duplicate profile in pom

* Update swagger annotations of get current quarter and fix usage of wrong implementation class for get current quarters

* Remove unused import in common.ts

* add dependency for hot reload in again

* [FM] Automated formating frontend

* readd local debug run config

---------

Co-authored-by: Miguel Lehmann <[email protected]>
Co-authored-by: Jannik Pulfer <[email protected]>
Co-authored-by: GitHub Actions <[email protected]>
  • Loading branch information
4 people authored and MasterEvarior committed Nov 6, 2024
1 parent ee34cf5 commit 08363f4
Show file tree
Hide file tree
Showing 14 changed files with 184 additions and 181 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import java.util.List;

@RestController
@RequestMapping("api/v1/quarters")
@RequestMapping("api/v2/quarters")
public class QuarterController {

private final QuarterBusinessService quarterBusinessService;
Expand All @@ -28,9 +28,17 @@ public QuarterController(QuarterBusinessService quarterBusinessService) {

@Operation(summary = "Get quarters", description = "Get a List of quarters depending on current date")
@ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Returned a List of quarters", content = {
@Content(mediaType = "application/json", schema = @Schema(implementation = TeamDto.class)) }) })
@Content(mediaType = "application/json", schema = @Schema(implementation = Quarter.class)) }) })
@GetMapping("")
public ResponseEntity<List<Quarter>> getCurrentQuarters() {
return ResponseEntity.status(HttpStatus.OK).body(this.quarterBusinessService.getQuarters());
}

@Operation(summary = "Get current quarter", description = "Get the current quarter depending on current date")
@ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Returned the current quarter", content = {
@Content(mediaType = "application/json", schema = @Schema(implementation = Quarter.class)) }) })
@GetMapping("/current")
public ResponseEntity<Quarter> getCurrentQuarter() {
return ResponseEntity.status(HttpStatus.OK).body(this.quarterBusinessService.getCurrentQuarter());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.BDDMockito;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
Expand Down Expand Up @@ -48,7 +49,7 @@ class QuarterControllerIT {
void shouldGetAllQuarters() throws Exception {
BDDMockito.given(quarterBusinessService.getQuarters()).willReturn(quaterList);

mvc.perform(get("/api/v1/quarters").contentType(MediaType.APPLICATION_JSON))
mvc.perform(get("/api/v2/quarters").contentType(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(3)))
.andExpect(jsonPath("$[0].id", Is.is(1))).andExpect(jsonPath("$[0].label", Is.is("GJ 22/23-Q2")))
.andExpect(jsonPath("$[0].startDate", Is.is(LocalDate.of(2022, 9, 1).toString())))
Expand All @@ -64,7 +65,14 @@ void shouldGetAllQuarters() throws Exception {
void shouldGetAllTeamsIfNoTeamsExists() throws Exception {
BDDMockito.given(quarterBusinessService.getQuarters()).willReturn(Collections.emptyList());

mvc.perform(get("/api/v1/quarters").contentType(MediaType.APPLICATION_JSON))
mvc.perform(get("/api/v2/quarters").contentType(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(0)));
}
}

@Test
void shouldCallCurrentQuarterAfterRequest() throws Exception {
mvc.perform(get("/api/v2/quarters/current").contentType(MediaType.APPLICATION_JSON));

BDDMockito.verify(quarterBusinessService, Mockito.times(1)).getCurrentQuarter();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { KeyResultMetric } from '../../shared/types/model/KeyResultMetric';
import { KeyResultOrdinal } from '../../shared/types/model/KeyResultOrdinal';
import { TranslateTestingModule } from 'ngx-translate-testing';
import * as de from '../../../assets/i18n/de.json';
import { Quarter } from '../../shared/types/model/Quarter';

describe('KeyResultFormComponent', () => {
let component: KeyResultFormComponent;
Expand Down Expand Up @@ -70,7 +71,7 @@ describe('KeyResultFormComponent', () => {
const keyResultObjective: KeyResultObjective = {
id: 2,
state: State.ONGOING,
quarter: { id: 1, label: 'GJ 22/23-Q2', endDate: new Date(), startDate: new Date() },
quarter: new Quarter(1, 'GJ 22/23-Q2', new Date(), new Date()),
};

const keyResultFormGroup = new FormGroup({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { DragDropModule } from '@angular/cdk/drag-drop';
import { UserService } from '../../services/user.service';
import { KeyResultFormComponent } from '../key-result-form/key-result-form.component';
import { Quarter } from '../../shared/types/model/Quarter';

describe('KeyresultDialogComponent', () => {
let component: KeyresultDialogComponent;
Expand Down Expand Up @@ -55,7 +56,7 @@ describe('KeyresultDialogComponent', () => {
let keyResultObjective: KeyResultObjective = {
id: 2,
state: State.ONGOING,
quarter: { id: 1, label: 'GJ 22/23-Q2', endDate: new Date(), startDate: new Date() },
quarter: new Quarter(1, 'GJ 22/23-Q2', new Date(), new Date()),
};

let fullKeyResultMetric = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<mat-form-field appearance="outline" class="bg-white header-form-field quarter-filter" subscriptSizing="dynamic">
<mat-select
[(ngModel)]="quarterId"
[(ngModel)]="currentQuarterId"
(ngModelChange)="changeDisplayedQuarter()"
ngDefaultControl
[attr.data-testId]="'quarterFilter'"
>
<mat-option *ngFor="let quarter of quarters | async; let i = index" [value]="quarter.id">
{{ getQuarterLabel(quarter, i) }}
<mat-option *ngFor="let quarter of quarters | async" [value]="quarter.id">
{{ quarter.fullLabel() }}
</mat-option>
</mat-select>
</mat-form-field>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { QuarterFilterComponent } from './quarter-filter.component';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { OverviewService } from '../../services/overview.service';
import { quarter } from '../../shared/testData';
import { Observable, of } from 'rxjs';
import { Quarter } from '../../shared/types/model/Quarter';
import { QuarterService } from '../../services/quarter.service';
Expand All @@ -21,16 +20,19 @@ const overviewService = {
};

const quarters = [
{ id: 999, label: 'Backlog', startDate: null, endDate: null },
{ ...quarter, id: 2 },
{ ...quarter, id: 5 },
{ ...quarter, id: 7 },
new Quarter(999, 'Backlog', null, null),
new Quarter(2, '23.02.2025', new Date(), new Date()),
new Quarter(5, '23.02.2025', new Date(), new Date()),
new Quarter(7, '23.02.2025', new Date(), new Date()),
];

const quarterService = {
getAllQuarters(): Observable<Quarter[]> {
return of(quarters);
},
getCurrentQuarter(): Observable<Quarter> {
return of(quarters[2]);
},
};

describe('QuarterFilterComponent', () => {
Expand Down Expand Up @@ -68,13 +70,14 @@ describe('QuarterFilterComponent', () => {

it('should set correct default quarter if no route param is defined', async () => {
jest.spyOn(component, 'changeDisplayedQuarter');
jest.spyOn(quarters[2] as any, 'isCurrent').mockReturnValue(true);
const quarterSelect = await loader.getHarness(MatSelectHarness);
expect(quarterSelect).toBeTruthy();
component.ngOnInit();
fixture.detectChanges();
expect(component.quarterId).toBe(quarters[2].id);
expect(component.currentQuarterId).toBe(quarters[2].id);
expect(await quarterSelect.getValueText()).toBe(quarters[2].label + ' Aktuell');
expect(component.changeDisplayedQuarter).toHaveBeenCalledTimes(0);
expect(component.changeDisplayedQuarter).toHaveBeenCalledTimes(1);
});

it('should set correct value in form according to route param', async () => {
Expand All @@ -89,7 +92,7 @@ describe('QuarterFilterComponent', () => {
component.ngOnInit();
fixture.detectChanges();

expect(component.quarterId).toBe(quarters[3].id);
expect(component.currentQuarterId).toBe(quarters[3].id);
expect(await quarterSelect.getValueText()).toBe(quarters[3].label);
expect(component.changeDisplayedQuarter).toHaveBeenCalledTimes(1);
});
Expand All @@ -106,7 +109,7 @@ describe('QuarterFilterComponent', () => {
routerHarness.detectChanges();
component.ngOnInit();
fixture.detectChanges();
expect(component.quarterId).toBe(quarters[2].id);
expect(component.currentQuarterId).toBe(quarters[2].id);
expect(await quarterSelect.getValueText()).toBe(quarters[2].label + ' Aktuell');
expect(component.changeDisplayedQuarter).toHaveBeenCalledTimes(1);
expect(router.url).toBe('/?quarter=' + quarters[2].id);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ChangeDetectionStrategy, Component, EventEmitter, OnInit, Output } from '@angular/core';
import { QuarterService } from '../../services/quarter.service';
import { Quarter } from '../../shared/types/model/Quarter';
import { BehaviorSubject } from 'rxjs';
import { BehaviorSubject, forkJoin } from 'rxjs';
import { ActivatedRoute, Router } from '@angular/router';
import { getQuarterLabel, getValueFromQuery } from '../../shared/common';
import { RefreshDataService } from '../../services/refresh-data.service';
import { getValueFromQuery } from '../../shared/common';

@Component({
selector: 'app-quarter-filter',
Expand All @@ -14,7 +14,7 @@ import { RefreshDataService } from '../../services/refresh-data.service';
export class QuarterFilterComponent implements OnInit {
quarters: BehaviorSubject<Quarter[]> = new BehaviorSubject<Quarter[]>([]);
@Output() quarterLabel$ = new EventEmitter<string>();
quarterId: number = -1;
currentQuarterId: number = -1;

constructor(
private quarterService: QuarterService,
Expand All @@ -24,35 +24,35 @@ export class QuarterFilterComponent implements OnInit {
) {}

ngOnInit() {
this.quarterService.getAllQuarters().subscribe((quarters) => {
const allQuarters$ = this.quarterService.getAllQuarters();
const currentQuarter$ = this.quarterService.getCurrentQuarter();
forkJoin([allQuarters$, currentQuarter$]).subscribe(([quarters, currentQuarter]) => {
this.quarters.next(quarters);
const quarterQuery = this.route.snapshot.queryParams['quarter'];
const quarterId: number = getValueFromQuery(quarterQuery)[0];
if (quarters.map((quarter) => quarter.id).includes(quarterId)) {
this.quarterId = quarterId;
this.currentQuarterId = quarterId;
this.changeDisplayedQuarter();
} else {
this.quarterId = quarters[2].id;
if (quarterQuery !== undefined) {
this.changeDisplayedQuarter();
} else {
this.currentQuarterId = currentQuarter.id;
this.changeDisplayedQuarter();

if (quarterQuery === undefined) {
this.refreshDataService.quarterFilterReady.next();
}
}
const quarterLabel = quarters.find((e) => e.id == this.quarterId)?.label || '';
const quarterLabel = quarters.find((e) => e.id == this.currentQuarterId)?.label || '';
this.quarterLabel$.next(quarterLabel);
});
}

changeDisplayedQuarter() {
const id = this.quarterId;
const id = this.currentQuarterId;
const quarterLabel = this.quarters.getValue().find((e) => e.id == id)?.label || '';
this.quarterLabel$.next(quarterLabel);

this.router
.navigate([], { queryParams: { quarter: id } })
.then(() => this.refreshDataService.quarterFilterReady.next());
}

protected readonly getQuarterLabel = getQuarterLabel;
}
14 changes: 12 additions & 2 deletions frontend/src/app/services/quarter.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Quarter } from '../shared/types/model/Quarter';
import { Observable } from 'rxjs';
import { map, Observable } from 'rxjs';

@Injectable({
providedIn: 'root',
Expand All @@ -10,6 +10,16 @@ export class QuarterService {
constructor(private http: HttpClient) {}

getAllQuarters(): Observable<Quarter[]> {
return this.http.get<Quarter[]>('/api/v1/quarters');
return this.http
.get<Quarter[]>('/api/v2/quarters')
.pipe(
map((quarters) =>
quarters.map((quarter) => new Quarter(quarter.id, quarter.label, quarter.startDate, quarter.endDate)),
),
);
}

getCurrentQuarter(): Observable<Quarter> {
return this.http.get<Quarter>('/api/v2/quarters/current');
}
}
4 changes: 0 additions & 4 deletions frontend/src/app/shared/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,6 @@ export function formInputCheck(form: FormGroup, propertyName: string) {
}
}

export function getQuarterLabel(quarter: any, index: number): string {
return index == 2 ? quarter.label + ' Aktuell' : quarter.label;
}

export function isMobileDevice() {
return window.navigator.userAgent.toLowerCase().includes('mobile');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
>
<ng-container *ngFor="let quarter of quarters$ | async; let i = index">
<option *ngIf="allowedOption(quarter)" [value]="quarter.id">
{{ getQuarterLabel(quarter, i) }}
{{ quarter.fullLabel() }}
</option>
</ng-container>
</select>
Expand Down
Loading

0 comments on commit 08363f4

Please sign in to comment.