-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature/624 refactor objective menu (#1078)
* Fix/fix git history (#1125) * fix history * fix hist * jar is now debuggable * add jar debug dev tools only on profile * 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 * refactor dialog calls with config by introducing a service * refactor frontend tests related to dialogService * remove backend/pom.xml from branch * introduce new objective menu action service to simplify dialog creation of dialog actions * refactor objective * reimplement generic menu * use pipe with map to generate menu entries * introduce afterAction property * add ObjectiveAfterActionFactory * introduce objectiveMenuAction file * refactor objective status tooltip * clean up objective menu action service * rename objective actions file * Try to fix frontend unit tests * restore staging.properties * fix angular build * place functions in related files instead of common.ts * restore angular config files * fix action service tests * add test for actions service * clean up * display correct options for draft and use replay subject * fix check-in tests * fix objective backlog tests * fix objective e2e tests * fix tabbing tests * fix tabbing tests * schtibitz e2e strategy from pulfer * remove console.log * restore focus * restore old frontend-test-action * clean pup * remove application.staging from pr * clean up tests of objective * fix e2e tests * check for focues of threedot menu after dialog closes --------- Co-authored-by: Manuel <[email protected]>
- Loading branch information
1 parent
1d8d99f
commit f3a8271
Showing
11 changed files
with
438 additions
and
358 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
frontend/src/app/components/objective/ObjectiveMenuActions.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { DialogService } from '../../services/dialog.service'; | ||
import { Objective } from '../../shared/types/model/Objective'; | ||
import { RefreshDataService } from '../../services/refresh-data.service'; | ||
import { ObjectiveMin } from '../../shared/types/model/ObjectiveMin'; | ||
import { ObjectiveFormComponent } from '../../shared/dialog/objective-dialog/objective-form.component'; | ||
import { CompleteDialogComponent } from '../../shared/dialog/complete-dialog/complete-dialog.component'; | ||
import { | ||
ObjectiveMenuAction, | ||
ObjectiveMenuAfterAction, | ||
ObjectiveMenuEntry, | ||
} from '../../services/objective-menu-actions.service'; | ||
import { ObjectiveMenuAfterActions } from './ObjectiveMenuAfterActions'; | ||
|
||
export class ObjectiveMenuActions { | ||
constructor( | ||
private readonly dialogService: DialogService, | ||
private readonly refreshDataService: RefreshDataService, | ||
private readonly afterActions: ObjectiveMenuAfterActions, | ||
) {} | ||
|
||
releaseFromQuarterAction(objective: ObjectiveMin): ObjectiveMenuEntry { | ||
const action: ObjectiveMenuAction = () => this.dialogService.openConfirmDialog('CONFIRMATION.RELEASE'); | ||
const afterAction: ObjectiveMenuAfterAction = (objective, dialogResult) => | ||
this.afterActions.releaseFromQuarter(objective); | ||
return { displayName: 'Objective veröffentlichen', action: action, afterAction: afterAction }; | ||
} | ||
|
||
releaseFromBacklogAction(objective: ObjectiveMin): ObjectiveMenuEntry { | ||
const config = { data: { objective: { objectiveId: objective.id }, action: 'releaseBacklog' } }; | ||
const action: ObjectiveMenuAction = () => this.dialogService.open(ObjectiveFormComponent, config); | ||
const afterAction: ObjectiveMenuAfterAction = () => this.refreshDataService.markDataRefresh(); | ||
return { displayName: 'Objective veröffentlichen', action: action, afterAction }; | ||
} | ||
|
||
editObjectiveAction(objective: ObjectiveMin): ObjectiveMenuEntry { | ||
const config = { data: { objective: { objectiveId: objective.id } } }; | ||
const action: ObjectiveMenuAction = () => this.dialogService.open(ObjectiveFormComponent, config); | ||
const afterAction: ObjectiveMenuAfterAction = () => { | ||
this.refreshDataService.markDataRefresh(); | ||
}; | ||
return { displayName: 'Objective bearbeiten', action: action, afterAction: afterAction }; | ||
} | ||
|
||
duplicateObjectiveAction(objective: ObjectiveMin): ObjectiveMenuEntry { | ||
const config = { data: { objective: { objectiveId: objective.id }, action: 'duplicate' } }; | ||
const action: ObjectiveMenuAction = () => this.dialogService.open(ObjectiveFormComponent, config); | ||
const afterAction: ObjectiveMenuAfterAction = () => this.refreshDataService.markDataRefresh(); | ||
return { displayName: 'Objective duplizieren', action: action, afterAction: afterAction }; | ||
} | ||
|
||
completeObjectiveAction(objective: ObjectiveMin): ObjectiveMenuEntry { | ||
const config = { | ||
data: { objectiveTitle: objective.title }, | ||
}; | ||
const action: ObjectiveMenuAction = () => this.dialogService.open(CompleteDialogComponent, config); | ||
const afterAction: ObjectiveMenuAfterAction = (obj: Objective, result: any) => | ||
this.afterActions.completeObjective(obj, result); | ||
|
||
return { displayName: 'Objective abschliessen', action: action, afterAction: afterAction }; | ||
} | ||
|
||
objectiveBackToDraft(): ObjectiveMenuEntry { | ||
const action: ObjectiveMenuAction = () => this.dialogService.openConfirmDialog('CONFIRMATION.TO_DRAFT'); | ||
const afterAction: ObjectiveMenuAfterAction = (obj: Objective, result: any) => | ||
this.afterActions.objectiveBackToDraft(obj); | ||
|
||
return { displayName: 'Objective als Draft speichern', action: action, afterAction: afterAction }; | ||
} | ||
|
||
objectiveReopen(): ObjectiveMenuEntry { | ||
const action: ObjectiveMenuAction = () => this.dialogService.openConfirmDialog('CONFIRMATION.REOPEN'); | ||
const afterAction: ObjectiveMenuAfterAction = (obj: Objective, result: any) => | ||
this.afterActions.objectiveReopen(obj); | ||
|
||
return { displayName: 'Objective wiedereröffnen', action: action, afterAction: afterAction }; | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
frontend/src/app/components/objective/ObjectiveMenuAfterActions.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { Objective } from '../../shared/types/model/Objective'; | ||
import { State } from '../../shared/types/enums/State'; | ||
import { Completed } from '../../shared/types/model/Completed'; | ||
import { ObjectiveService } from '../../services/objective.service'; | ||
import { RefreshDataService } from '../../services/refresh-data.service'; | ||
|
||
export class ObjectiveMenuAfterActions { | ||
constructor( | ||
private readonly objectiveService: ObjectiveService, | ||
private readonly refreshDataService: RefreshDataService, | ||
) {} | ||
|
||
completeObjective(objective: Objective, result: { endState: string; comment: string | null; objective: any }) { | ||
objective.state = result.endState as State; | ||
const completed: Completed = { | ||
id: null, | ||
version: objective.version, | ||
objective: objective, | ||
comment: result.comment, | ||
}; | ||
this.objectiveService.updateObjective(objective).subscribe(() => { | ||
this.objectiveService.createCompleted(completed).subscribe(() => { | ||
this.refreshDataService.markDataRefresh(); | ||
}); | ||
}); | ||
} | ||
|
||
releaseFromQuarter(objective: Objective) { | ||
objective.state = 'ONGOING' as State; | ||
this.objectiveService.updateObjective(objective).subscribe(() => { | ||
this.refreshDataService.markDataRefresh(); | ||
}); | ||
} | ||
|
||
objectiveBackToDraft(objective: Objective) { | ||
objective.state = 'DRAFT' as State; | ||
this.objectiveService.updateObjective(objective).subscribe(() => { | ||
this.refreshDataService.markDataRefresh(); | ||
}); | ||
} | ||
|
||
objectiveReopen(objective: Objective) { | ||
objective.state = 'ONGOING' as State; | ||
this.objectiveService.updateObjective(objective).subscribe(() => { | ||
this.objectiveService.deleteCompleted(objective.id).subscribe(() => { | ||
this.refreshDataService.markDataRefresh(); | ||
}); | ||
}); | ||
} | ||
} |
151 changes: 76 additions & 75 deletions
151
frontend/src/app/components/objective/objective.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,82 @@ | ||
<div | ||
(click)="openObjectiveDetail()" | ||
(keydown.enter)="openObjectiveDetail()" | ||
*ngIf="objective$ | async as objective" | ||
[attr.data-testId]="'objective'" | ||
class="objective rounded-3 bg-white w-100 cursor-pointer focus-outline" | ||
tabindex="0" | ||
> | ||
<div class="row mx-1"> | ||
<section class="d-flex mb-3 mt-3 justify-content-between pe-0"> | ||
<section class="d-flex gap-2 align-items-start fit-content objective-title"> | ||
<img | ||
<ng-container *ngIf="objective$ | async as objective"> | ||
<div | ||
(click)="openObjectiveDetail(objective.id)" | ||
(keydown.enter)="openObjectiveDetail(objective.id)" | ||
[attr.data-testId]="'objective'" | ||
class="objective rounded-3 bg-white w-100 cursor-pointer focus-outline" | ||
tabindex="0" | ||
> | ||
<div class="row mx-1"> | ||
<section class="d-flex mb-3 mt-3 justify-content-between pe-0"> | ||
<section class="d-flex gap-2 align-items-start fit-content objective-title"> | ||
<img | ||
(click)="$event.stopPropagation()" | ||
[attr.data-testId]="'objective-state'" | ||
[src]="'assets/icons/' + objective.state" | ||
alt="The objectives state" | ||
class="icon" | ||
matTooltip="{{ getStateTooltip(objective.state) }}" | ||
matTooltipPosition="above" | ||
/> | ||
<h2 class="title fit-content">{{ objective.title }}</h2> | ||
</section> | ||
<button | ||
#menuButton | ||
*ngIf="isWritable" | ||
class="icon-button three-dot-menu focus-outline" | ||
[matMenuTriggerFor]="objectiveMenu" | ||
(click)="$event.stopPropagation()" | ||
[attr.data-testId]="'objective-state'" | ||
[src]="'assets/icons/' + objective.state" | ||
alt="The objectives state" | ||
class="icon" | ||
matTooltip="{{ getStateTooltip() + ' ' + formatObjectiveState(objective.state) }}" | ||
matTooltipPosition="above" | ||
/> | ||
<h2 class="title fit-content">{{ objective.title }}</h2> | ||
(keydown.enter)="$event.stopPropagation()" | ||
[attr.data-testId]="'three-dot-menu'" | ||
> | ||
<img src="../assets/icons/three-dot-menu-icon.svg" alt="menu icon" class="text-white menu-scale" /> | ||
</button> | ||
</section> | ||
<button | ||
#menuButton | ||
*ngIf="isWritable" | ||
class="icon-button three-dot-menu focus-outline" | ||
[matMenuTriggerFor]="objectiveMenu" | ||
(click)="$event.stopPropagation(); getMenu()" | ||
(keydown.enter)="$event.stopPropagation()" | ||
[attr.data-testId]="'three-dot-menu'" | ||
> | ||
<img src="../assets/icons/three-dot-menu-icon.svg" alt="menu icon" class="text-white menu-scale" /> | ||
</button> | ||
</section> | ||
|
||
<div class="d-flex px-3 gap-3 flex-column"> | ||
<app-keyresult | ||
*ngFor="let keyResult of objective.keyResults; trackBy: trackByFn" | ||
class="border-0 p-0" | ||
(click)="$event.stopPropagation()" | ||
(keydown.enter)="$event.stopPropagation()" | ||
[keyResult]="keyResult" | ||
[attr.data-testId]="'keyresult'" | ||
></app-keyresult> | ||
</div> | ||
<div class="d-flex px-3 gap-3 flex-column"> | ||
<app-keyresult | ||
*ngFor="let keyResult of objective.keyResults; trackBy: trackByFn" | ||
class="border-0 p-0" | ||
(click)="$event.stopPropagation()" | ||
(keydown.enter)="$event.stopPropagation()" | ||
[keyResult]="keyResult" | ||
[attr.data-testId]="'keyresult'" | ||
></app-keyresult> | ||
</div> | ||
|
||
<section class="p-0 py-2 m-0"> | ||
<button | ||
*ngIf="!isComplete && isWritable" | ||
mat-button | ||
color="primary" | ||
class="fw-bold px-0 pe-2 ms-2" | ||
[attr.data-testId]="'add-keyResult'" | ||
(click)="openAddKeyResultDialog(); $event.stopPropagation()" | ||
(keydown.enter)="$event.stopPropagation()" | ||
> | ||
<span class="d-flex align-items-center add-text"> | ||
<img alt="Add key-result button" class="add-cross-button" src="../../../assets/icons/new-icon.svg" /> | ||
Key Result hinzufügen | ||
</span> | ||
</button> | ||
</section> | ||
<section class="p-0 py-2 m-0"> | ||
<button | ||
*ngIf="!isObjectiveComplete(this.objective) && isWritable" | ||
mat-button | ||
color="primary" | ||
class="fw-bold px-0 pe-2 ms-2" | ||
[attr.data-testId]="'add-keyResult'" | ||
(click)="openAddKeyResultDialog(objective); $event.stopPropagation()" | ||
(keydown.enter)="$event.stopPropagation()" | ||
> | ||
<span class="d-flex align-items-center add-text"> | ||
<img alt="Add key-result button" class="add-cross-button" src="../../../assets/icons/new-icon.svg" /> | ||
Key Result hinzufügen | ||
</span> | ||
</button> | ||
</section> | ||
</div> | ||
</div> | ||
</div> | ||
<mat-menu | ||
#objectiveMenu="matMenu" | ||
[class]="'objective-three-dot-menu'" | ||
class="pt-2 pb-2" | ||
xPosition="before" | ||
yPosition="below" | ||
> | ||
<button | ||
(click)="redirect(menuEntry)" | ||
*ngFor="let menuEntry of menuEntries" | ||
[attr.data-testId]="'objective-menu'" | ||
class="objective-menu-option" | ||
mat-menu-item | ||
<mat-menu | ||
#objectiveMenu="matMenu" | ||
[class]="'objective-three-dot-menu'" | ||
class="pt-2 pb-2" | ||
xPosition="before" | ||
yPosition="below" | ||
> | ||
{{ menuEntry.displayName }} | ||
</button> | ||
</mat-menu> | ||
<button | ||
(click)="redirect(menuEntry, objective)" | ||
*ngFor="let menuEntry of menuEntries | async" | ||
[attr.data-testId]="'objective-menu'" | ||
class="objective-menu-option" | ||
mat-menu-item | ||
> | ||
{{ menuEntry.displayName }} | ||
</button> | ||
</mat-menu> | ||
</ng-container> |
Oops, something went wrong.