Skip to content

Commit

Permalink
Implement typeahead
Browse files Browse the repository at this point in the history
  • Loading branch information
lkleisa committed May 23, 2024
1 parent f39ece5 commit 38a0863
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 82 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package ch.puzzle.okr.controller;

import ch.puzzle.okr.dto.ObjectiveAlignmentsDto;
import ch.puzzle.okr.dto.AlignmentDto;
import ch.puzzle.okr.dto.ObjectiveDto;
import ch.puzzle.okr.mapper.ObjectiveMapper;
import ch.puzzle.okr.models.Objective;
Expand Down Expand Up @@ -48,11 +48,11 @@ public ResponseEntity<ObjectiveDto> getObjective(
@Operation(summary = "Get Alignment possibilities", description = "Get all possibilities to create an Alignment")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Returned all Alignment possibilities for an Objective", content = {
@Content(mediaType = "application/json", schema = @Schema(implementation = ObjectiveAlignmentsDto.class)) }),
@Content(mediaType = "application/json", schema = @Schema(implementation = AlignmentDto.class)) }),
@ApiResponse(responseCode = "401", description = "Not authorized to get Alignment possibilities", content = @Content),
@ApiResponse(responseCode = "404", description = "Did not find any possibilities to create an Alignment", content = @Content) })
@GetMapping("/alignmentPossibilities/{quarterId}")
public ResponseEntity<List<ObjectiveAlignmentsDto>> getAlignmentPossibilities(
public ResponseEntity<List<AlignmentDto>> getAlignmentPossibilities(
@Parameter(description = "The Quarter ID for getting Alignment possibilities.", required = true) @PathVariable Long quarterId) {
return ResponseEntity.status(HttpStatus.OK)
.body(objectiveAuthorizationService.getAlignmentPossibilities(quarterId));
Expand Down
6 changes: 6 additions & 0 deletions backend/src/main/java/ch/puzzle/okr/dto/AlignmentDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package ch.puzzle.okr.dto;

import java.util.List;

public record AlignmentDto(Long teamId, String teamName, List<AlignmentObjectDto> alignmentObjectDtos) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package ch.puzzle.okr.dto;

public record AlignmentObjectDto(Long objectId, String objectTitle, String objectType) {
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package ch.puzzle.okr.service.authorization;

import ch.puzzle.okr.dto.ObjectiveAlignmentsDto;
import ch.puzzle.okr.dto.AlignmentDto;
import ch.puzzle.okr.models.Objective;
import ch.puzzle.okr.models.authorization.AuthorizationUser;
import ch.puzzle.okr.service.business.ObjectiveBusinessService;
Expand All @@ -22,7 +22,7 @@ public Objective duplicateEntity(Long id, Objective objective) {
return getBusinessService().duplicateObjective(id, objective, authorizationUser);
}

public List<ObjectiveAlignmentsDto> getAlignmentPossibilities(Long quarterId) {
public List<AlignmentDto> getAlignmentPossibilities(Long quarterId) {
return getBusinessService().getAlignmentPossibilities(quarterId);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package ch.puzzle.okr.service.business;

import ch.puzzle.okr.dto.ObjectiveAlignmentsDto;
import ch.puzzle.okr.dto.keyresult.KeyResultAlignmentsDto;
import ch.puzzle.okr.dto.AlignmentDto;
import ch.puzzle.okr.dto.AlignmentObjectDto;
import ch.puzzle.okr.models.Objective;
import ch.puzzle.okr.models.Team;
import ch.puzzle.okr.models.authorization.AuthorizationUser;
import ch.puzzle.okr.models.keyresult.KeyResult;
import ch.puzzle.okr.models.keyresult.KeyResultMetric;
Expand All @@ -16,9 +17,7 @@
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.*;

import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC;
import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL;
Expand Down Expand Up @@ -52,26 +51,40 @@ public Objective getEntityById(Long id) {
return objective;
}

public List<ObjectiveAlignmentsDto> getAlignmentPossibilities(Long quarterId) {
public List<AlignmentDto> getAlignmentPossibilities(Long quarterId) {
validator.validateOnGet(quarterId);

List<Objective> objectivesByQuarter = objectivePersistenceService.findObjectiveByQuarterId(quarterId);
List<ObjectiveAlignmentsDto> objectiveAlignmentsDtos = new ArrayList<>();

objectivesByQuarter.forEach(objective -> {
List<KeyResult> keyResults = keyResultBusinessService.getAllKeyResultsByObjective(objective.getId());
List<KeyResultAlignmentsDto> keyResultAlignmentsDtos = new ArrayList<>();
keyResults.forEach(keyResult -> {
KeyResultAlignmentsDto keyResultAlignmentsDto = new KeyResultAlignmentsDto(keyResult.getId(),
"K - " + keyResult.getTitle());
keyResultAlignmentsDtos.add(keyResultAlignmentsDto);
List<AlignmentDto> alignmentDtoList = new ArrayList<>();

List<Team> teamList = new ArrayList<>();
objectivesByQuarter.forEach(objective -> teamList.add(objective.getTeam()));
Set<Team> set = new HashSet<>(teamList);
teamList.clear();
teamList.addAll(set);

teamList.forEach(team -> {
List<Objective> filteredObjectiveList = objectivesByQuarter.stream()
.filter(objective -> objective.getTeam().equals(team)).toList();
List<AlignmentObjectDto> alignmentObjectDtos = new ArrayList<>();

filteredObjectiveList.forEach(objective -> {
AlignmentObjectDto objectiveDto = new AlignmentObjectDto(objective.getId(),
"O - " + objective.getTitle(), "objective");
alignmentObjectDtos.add(objectiveDto);

List<KeyResult> keyResults = keyResultBusinessService.getAllKeyResultsByObjective(objective.getId());
keyResults.forEach(keyResult -> {
AlignmentObjectDto keyResultDto = new AlignmentObjectDto(keyResult.getId(),
"KR - " + keyResult.getTitle(), "keyResult");
alignmentObjectDtos.add(keyResultDto);
});
});
ObjectiveAlignmentsDto objectiveAlignmentsDto = new ObjectiveAlignmentsDto(objective.getId(),
"O - " + objective.getTitle(), keyResultAlignmentsDtos);
objectiveAlignmentsDtos.add(objectiveAlignmentsDto);
AlignmentDto alignmentDto = new AlignmentDto(team.getId(), team.getName(), alignmentObjectDtos);
alignmentDtoList.add(alignmentDto);
});

return objectiveAlignmentsDtos;
return alignmentDtoList;
}

public List<Objective> getEntitiesByTeamId(Long id) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<section mat-dialog-title>
<div *ngIf="this.data.action == 'duplicate'">
<app-dialog-header
[dialogTitle]="'Objective von ' + (this.currentTeam | async)?.name + ' duplizieren'"
[dialogTitle]="'Objective von ' + (this.currentTeam$ | async)?.name + ' duplizieren'"
></app-dialog-header>
</div>
<div *ngIf="this.data.action == 'releaseBacklog'">
Expand All @@ -10,11 +10,11 @@
<div *ngIf="this.data.action != 'duplicate'">
<app-dialog-header
*ngIf="!data.objective.objectiveId"
[dialogTitle]="'Objective für ' + (this.currentTeam | async)?.name + ' erfassen'"
[dialogTitle]="'Objective für ' + (this.currentTeam$ | async)?.name + ' erfassen'"
></app-dialog-header>
<app-dialog-header
*ngIf="data.objective.objectiveId && this.data.action != 'releaseBacklog'"
[dialogTitle]="'Objective von ' + (this.currentTeam | async)?.name + ' bearbeiten'"
[dialogTitle]="'Objective von ' + (this.currentTeam$ | async)?.name + ' bearbeiten'"
></app-dialog-header>
</div>
</section>
Expand Down Expand Up @@ -68,25 +68,27 @@
</div>

<div class="d-flex flex-column gap-2 col-6">
<label class="text-black" for="alignment">Bezug (optional)</label>
<select
class="custom-select bg-white select-width"
<label class="text-black">Bezug (optional)</label>
<input
#input
type="text"
formControlName="alignment"
id="alignment"
(change)="changeFirstAlignmentPossibility()"
[attr.data-testId]="'alignmentSelect'"
>
<ng-container *ngFor="let alignment of alignmentPossibilities$ | async; let i = index">
<option [value]="'O' + alignment.objectiveId">
{{ alignment.objectiveTitle }}
</option>
<ng-container *ngFor="let keyResult of alignment.keyResultAlignmentsDtos; let i = index">
<option [value]="'K' + keyResult.keyResultId">
{{ keyResult.keyResultTitle }}
</option>
</ng-container>
</ng-container>
</select>
class="alignment-input"
placeholder="{{ filteredOptions.length == 0 ? 'Kein Alignment vorhanden' : 'Bezug wählen' }}"
[matAutocomplete]="auto"
(input)="filter()"
(focus)="filter(); input.select()"
[value]="displayedValue"
/>
<mat-autocomplete requireSelection #auto="matAutocomplete" [displayWith]="displayWith">
@for (group of filteredOptions; track group) {
<mat-optgroup [label]="group.teamName">
@for (alignmentObject of group.alignmentObjectDtos; track alignmentObject) {
<mat-option [value]="alignmentObject">{{ alignmentObject.objectTitle }}</mat-option>
}
</mat-optgroup>
}
</mat-autocomplete>
</div>
</div>
<mat-checkbox
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,18 @@
.select-width {
width: 92%;
}

.mat-mdc-option {
margin-bottom: 5px;
}

.alignment-input {
border: solid 1px #909090;
padding: 0.44rem 0.625rem 0.375rem 0.625rem;
cursor: pointer;
width: 92%;
height: 1.18rem;
box-sizing: content-box;
overflow: hidden;
text-overflow: ellipsis;
}
Loading

0 comments on commit 38a0863

Please sign in to comment.