From 6fe4f9a083630f3be2b06260786dd955b81af443 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 15 Oct 2024 08:46:30 +0200 Subject: [PATCH 01/28] update config --- backend/src/main/resources/application-staging.properties | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/src/main/resources/application-staging.properties b/backend/src/main/resources/application-staging.properties index 38e4a47571..e15a7283ee 100644 --- a/backend/src/main/resources/application-staging.properties +++ b/backend/src/main/resources/application-staging.properties @@ -1,7 +1,6 @@ # logging level for staging -logging.level.ch.puzzle.okr=DEBUG -#logging.level.org.flywaydb.core=DEBUG - +logging.level.ch.puzzle.okr=TRACE +logging.level.org.springframework.security=TRACE connect.src=http://localhost:8544 http://localhost:8545 From 60857ddd4f1e5f09c8615bb32045decba5d14be9 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 15 Oct 2024 10:50:14 +0200 Subject: [PATCH 02/28] jar is now debuggable --- .run/OkrApplication-local-prod-debug.run.xml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 .run/OkrApplication-local-prod-debug.run.xml diff --git a/.run/OkrApplication-local-prod-debug.run.xml b/.run/OkrApplication-local-prod-debug.run.xml new file mode 100755 index 0000000000..15ae63f4ef --- /dev/null +++ b/.run/OkrApplication-local-prod-debug.run.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file From 99134e991a09f082287a11868f0abb57e07b01b0 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 15 Oct 2024 10:57:07 +0200 Subject: [PATCH 03/28] add jar debug dev tools only on profile --- backend/pom.xml | 27 --------------------------- pom.xml | 1 - 2 files changed, 28 deletions(-) diff --git a/backend/pom.xml b/backend/pom.xml index 64e1227cbc..6d5f4013ac 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -83,15 +83,6 @@ 3.26.3 test - - org.springframework.boot - spring-boot-devtools - - - org.springframework - springloaded - 1.2.8.RELEASE - @@ -300,23 +291,5 @@ - - no-formatter - - - - net.revelc.code.formatter - formatter-maven-plugin - 2.24.1 - - - code-format - none - - - - - - diff --git a/pom.xml b/pom.xml index 06042ef745..828c336c1e 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,6 @@ build-for-docker debug - no-formatter From e89883c8f056db4a76c33285f2cf05ac3cdf4276 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 15 Oct 2024 11:29:16 +0200 Subject: [PATCH 04/28] change log levels --- backend/src/main/resources/application-staging.properties | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/src/main/resources/application-staging.properties b/backend/src/main/resources/application-staging.properties index e15a7283ee..91d48fcb5e 100644 --- a/backend/src/main/resources/application-staging.properties +++ b/backend/src/main/resources/application-staging.properties @@ -1,6 +1,8 @@ # logging level for staging -logging.level.ch.puzzle.okr=TRACE -logging.level.org.springframework.security=TRACE +logging.level.ch.puzzle.okr=DEBUG +logging.level.org.springframework.security=DEBUG +logging.level.org.flywaydb.core=DEBUG + connect.src=http://localhost:8544 http://localhost:8545 From 764b2f93e1ddc4ea25058648d154b6e65323b30b Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 15 Oct 2024 12:10:39 +0200 Subject: [PATCH 05/28] try to fix autorestart of spring --- backend/src/main/resources/application-staging.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/resources/application-staging.properties b/backend/src/main/resources/application-staging.properties index 91d48fcb5e..a66d43876d 100644 --- a/backend/src/main/resources/application-staging.properties +++ b/backend/src/main/resources/application-staging.properties @@ -1,7 +1,7 @@ # logging level for staging logging.level.ch.puzzle.okr=DEBUG logging.level.org.springframework.security=DEBUG -logging.level.org.flywaydb.core=DEBUG +#logging.level.org.flywaydb.core=DEBUG connect.src=http://localhost:8544 http://localhost:8545 From b80434196ec10fa0a87de3b999598f65448fa843 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Thu, 17 Oct 2024 08:28:59 +0200 Subject: [PATCH 06/28] rename intelij config and change log level of spring to debug in staging config --- .run/OkrApplication-local-prod-debug.run.xml | 17 ----------------- .../resources/application-staging.properties | 1 - 2 files changed, 18 deletions(-) delete mode 100755 .run/OkrApplication-local-prod-debug.run.xml diff --git a/.run/OkrApplication-local-prod-debug.run.xml b/.run/OkrApplication-local-prod-debug.run.xml deleted file mode 100755 index 15ae63f4ef..0000000000 --- a/.run/OkrApplication-local-prod-debug.run.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/backend/src/main/resources/application-staging.properties b/backend/src/main/resources/application-staging.properties index a66d43876d..38e4a47571 100644 --- a/backend/src/main/resources/application-staging.properties +++ b/backend/src/main/resources/application-staging.properties @@ -1,6 +1,5 @@ # logging level for staging logging.level.ch.puzzle.okr=DEBUG -logging.level.org.springframework.security=DEBUG #logging.level.org.flywaydb.core=DEBUG From bb1232184e3cae3b67cf7ecccf7c35dc1a80bf93 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 18 Oct 2024 12:15:51 +0200 Subject: [PATCH 07/28] exclude formatter plugin in build for docker --- backend/pom.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/backend/pom.xml b/backend/pom.xml index 6d5f4013ac..827af9b360 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -259,6 +259,17 @@ org.springframework.boot spring-boot-maven-plugin + + net.revelc.code.formatter + formatter-maven-plugin + 2.23.0 + + + code-format + none + + + From 4edaac11b639fb215bc366101c9ce0653986ef4e Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 18 Oct 2024 12:25:52 +0200 Subject: [PATCH 08/28] use external profile to disable formatter --- backend/pom.xml | 29 ++++++++++++++++++----------- pom.xml | 1 + 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/backend/pom.xml b/backend/pom.xml index 827af9b360..ded5b15af4 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -259,17 +259,6 @@ org.springframework.boot spring-boot-maven-plugin - - net.revelc.code.formatter - formatter-maven-plugin - 2.23.0 - - - code-format - none - - - @@ -302,5 +291,23 @@ + + no-formatter + + + + net.revelc.code.formatter + formatter-maven-plugin + 2.23.0 + + + code-format + none + + + + + + diff --git a/pom.xml b/pom.xml index 828c336c1e..06042ef745 100644 --- a/pom.xml +++ b/pom.xml @@ -51,6 +51,7 @@ build-for-docker debug + no-formatter From 9ee31410929b79562f793e524baf03c29a5399de Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 18 Oct 2024 12:28:39 +0200 Subject: [PATCH 09/28] clean up --- .../src/main/resources/application-staging.properties | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/backend/src/main/resources/application-staging.properties b/backend/src/main/resources/application-staging.properties index 38e4a47571..31ce92a3c2 100644 --- a/backend/src/main/resources/application-staging.properties +++ b/backend/src/main/resources/application-staging.properties @@ -1,12 +1,10 @@ # logging level for staging -logging.level.ch.puzzle.okr=DEBUG -#logging.level.org.flywaydb.core=DEBUG - +logging.level.org.springframework=debug connect.src=http://localhost:8544 http://localhost:8545 -hibernate.connection.url=jdbc:postgresql://localhost:5432/okr +hibernate.connection.url=jdbc:postgresql://okr-dev-db:5432/okr hibernate.connection.username=user hibernate.connection.password=pwd hibernate.multiTenancy=SCHEMA @@ -18,7 +16,7 @@ okr.datasource.driver-class-name=org.postgresql.Driver okr.user.champion.usernames=peggimann # pitc -okr.tenants.pitc.datasource.url=jdbc:postgresql://localhost:5432/okr +okr.tenants.pitc.datasource.url=jdbc:postgresql://okr-dev-db:5432/okr okr.tenants.pitc.datasource.username=user okr.tenants.pitc.datasource.password=pwd okr.tenants.pitc.datasource.schema=okr_pitc @@ -29,7 +27,7 @@ okr.tenants.pitc.security.oauth2.frontend.client-id=pitc_okr_staging # acme -okr.tenants.acme.datasource.url=jdbc:postgresql://localhost:5432/okr +okr.tenants.acme.datasource.url=jdbc:postgresql://okr-dev-db:5432/okr okr.tenants.acme.datasource.username=user okr.tenants.acme.datasource.password=pwd okr.tenants.acme.datasource.schema=okr_acme From 6cbad7f6ebca50137e65174a2a185cea2a9443f2 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 18 Oct 2024 07:21:41 +0200 Subject: [PATCH 10/28] fix display of tangram --- .../shared/custom/okr-tangram/okr-tangram.component.html | 2 +- .../shared/custom/okr-tangram/okr-tangram.component.ts | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.html b/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.html index 92bb32f252..abd7776d79 100644 --- a/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.html +++ b/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.html @@ -1 +1 @@ -okr-logo +okr-logo diff --git a/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.ts b/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.ts index 5fb7a3c399..4fee8f4e6f 100644 --- a/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.ts +++ b/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; import { ConfigService } from '../../../services/config.service'; -import { map, Observable } from 'rxjs'; +import { BehaviorSubject, map, Observable, Subject, Subscription } from 'rxjs'; @Component({ selector: 'app-okr-tangram', @@ -8,12 +8,10 @@ import { map, Observable } from 'rxjs'; styleUrl: 'okr-tangram.component.scss', }) export class OkrTangramComponent { - private readonly DEFAULT_TRIANGLE_SRC = 'assets/images/empty.svg'; + private readonly defaultTrianglesSrc = 'assets/images/empty.svg'; trianglesSrc$ = new Observable(); constructor(private readonly configService: ConfigService) { - this.trianglesSrc$ = this.configService.config$.pipe( - map((config) => config.triangles || this.DEFAULT_TRIANGLE_SRC), - ); + this.trianglesSrc$ = this.configService.config$.pipe(map((config) => config.triangles || this.defaultTrianglesSrc)); } } From 510a8467bcc82d5b9b65e48fb39eaf48d05d0d42 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 18 Oct 2024 07:44:53 +0200 Subject: [PATCH 11/28] update test and change const cname --- .../app/shared/custom/okr-tangram/okr-tangram.component.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.ts b/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.ts index 4fee8f4e6f..ccb0658056 100644 --- a/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.ts +++ b/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.ts @@ -8,10 +8,12 @@ import { BehaviorSubject, map, Observable, Subject, Subscription } from 'rxjs'; styleUrl: 'okr-tangram.component.scss', }) export class OkrTangramComponent { - private readonly defaultTrianglesSrc = 'assets/images/empty.svg'; + private readonly DEFAULT_TRIANGLE_SRC = 'assets/images/empty.svg'; trianglesSrc$ = new Observable(); constructor(private readonly configService: ConfigService) { - this.trianglesSrc$ = this.configService.config$.pipe(map((config) => config.triangles || this.defaultTrianglesSrc)); + this.trianglesSrc$ = this.configService.config$.pipe( + map((config) => config.triangles || this.DEFAULT_TRIANGLE_SRC), + ); } } From c50cffe0e9f8daced7c09f5a96c1ec8e6752f8ba Mon Sep 17 00:00:00 2001 From: nevio18324 <141240169+nevio18324@users.noreply.github.com> Date: Wed, 23 Oct 2024 12:01:37 +0200 Subject: [PATCH 12/28] add a Observable that triggers a refresh when called (#1041) * jar is now debuggable * rename folder * add a Observable that triggers a refresh when called * add destroy observable to stop subscription of reloadKeySubject * add tests to observables --------- Co-authored-by: Yanick Minder --- .run/OkrApplication-local-prod-debug.run.xml | 17 +++++++++++++++++ backend/pom.xml | 9 +++++++++ .../keyresult-detail.component.ts | 1 + 3 files changed, 27 insertions(+) create mode 100755 .run/OkrApplication-local-prod-debug.run.xml diff --git a/.run/OkrApplication-local-prod-debug.run.xml b/.run/OkrApplication-local-prod-debug.run.xml new file mode 100755 index 0000000000..15ae63f4ef --- /dev/null +++ b/.run/OkrApplication-local-prod-debug.run.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/backend/pom.xml b/backend/pom.xml index ded5b15af4..519e08b05e 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -83,6 +83,15 @@ 3.26.3 test + + org.springframework.boot + spring-boot-devtools + + + org.springframework + springloaded + 1.2.8.RELEASE + diff --git a/frontend/src/app/components/keyresult-detail/keyresult-detail.component.ts b/frontend/src/app/components/keyresult-detail/keyresult-detail.component.ts index d2b5763824..21adfbc536 100644 --- a/frontend/src/app/components/keyresult-detail/keyresult-detail.component.ts +++ b/frontend/src/app/components/keyresult-detail/keyresult-detail.component.ts @@ -4,6 +4,7 @@ import { KeyresultService } from '../../services/keyresult.service'; import { KeyResultMetric } from '../../shared/types/model/KeyResultMetric'; import { KeyResultOrdinal } from '../../shared/types/model/KeyResultOrdinal'; import { CheckInHistoryDialogComponent } from '../check-in-history-dialog/check-in-history-dialog.component'; +import { MatDialog } from '@angular/material/dialog'; import { BehaviorSubject, catchError, EMPTY, Subject, takeUntil } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; import { RefreshDataService } from '../../services/refresh-data.service'; From dac23cbb1954dc010173bd37d8b82ef5792683ab Mon Sep 17 00:00:00 2001 From: Yanick Minder <79108296+kcinay055679@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:07:27 +0200 Subject: [PATCH 13/28] Feature/624 Dialog creation refactoring using a service (#1045) * add jar debug dev tools only on profile * refactor dialog calls with config by introducing a service * convert all confirmation dialog texts to i18n texts * use refactored confirmation component * fix string and use interface for confirm dialog data * Update title of delete confirmation * clean up dialog service * refactor frontend tests related to dialogService * display correct dialog in objective * fix objective release dialog * refactor dialog responsiveness * clean up dialog service * remove backend/pom.xml from branch * update translations and fix release dialog * update dialog.service.ts --- frontend/cypress/e2e/objective.cy.ts | 4 +- .../check-in-history-dialog.component.spec.ts | 12 +- .../keyresult-detail.component.ts | 1 - .../keyresult-dialog.component.ts | 2 +- .../objective/objective.component.ts | 206 ++++++++++++++++-- .../src/app/services/dialog.service.spec.ts | 68 +----- frontend/src/app/services/dialog.service.ts | 18 +- .../okr-tangram/okr-tangram.component.ts | 2 +- .../confirm-dialog.component.spec.ts | 6 +- .../objective-form.component.ts | 3 +- .../add-edit-team-dialog.component.spec.ts | 6 +- .../member-detail.component.spec.ts | 7 +- .../member-detail/member-detail.component.ts | 11 +- .../member-list-table.component.spec.ts | 4 +- .../member-list-table.component.ts | 12 +- .../member-list/member-list.component.spec.ts | 5 +- .../member-list/member-list.component.ts | 11 +- frontend/src/assets/i18n/de.json | 32 +++ .../src/style/custom_angular.components.scss | 9 + frontend/src/style/styles.scss | 46 ---- 20 files changed, 273 insertions(+), 192 deletions(-) diff --git a/frontend/cypress/e2e/objective.cy.ts b/frontend/cypress/e2e/objective.cy.ts index afca9c4c76..34b4611d30 100644 --- a/frontend/cypress/e2e/objective.cy.ts +++ b/frontend/cypress/e2e/objective.cy.ts @@ -30,7 +30,7 @@ describe('OKR Objective e2e tests', () => { .click(); cy.contains('Objective veröffentlichen'); cy.contains('Soll dieses Objective veröffentlicht werden?'); - cy.getByTestId('confirm-yes').click(); + cy.getByTestId('confirmYes').click(); cy.getByTestId('objective') .filter(':contains(A objective in state draft)') .last() @@ -158,7 +158,7 @@ describe('OKR Objective e2e tests', () => { .tabForward(); cy.contains('Objective als Draft speichern'); cy.contains('Soll dieses Objective als Draft gespeichert werden?'); - cy.getByTestId('confirm-yes').click(); + cy.focused().click().wait(500); cy.getByTestId('objective') .filter(':contains("This objective will be returned to draft state")') diff --git a/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.spec.ts b/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.spec.ts index ee75865c64..5ed4650bd6 100644 --- a/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.spec.ts +++ b/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.spec.ts @@ -7,13 +7,10 @@ import { checkInMetric, checkInMetricWriteableFalse, keyResult } from '../../sha import { By } from '@angular/platform-browser'; import { DialogService } from '../../services/dialog.service'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { DialogHeaderComponent } from '../../shared/custom/dialog-header/dialog-header.component'; import { MatIconModule } from '@angular/material/icon'; import { SpinnerComponent } from '../../shared/custom/spinner/spinner.component'; import { MatProgressSpinner } from '@angular/material/progress-spinner'; -import { provideRouter } from '@angular/router'; -import { provideHttpClient } from '@angular/common/http'; -import { DialogTemplateCoreComponent } from '../../shared/custom/dialog-template-core/dialog-template-core.component'; -import { MatDividerModule } from '@angular/material/divider'; const checkInService = { getAllCheckInOfKeyResult: jest.fn(), @@ -25,13 +22,10 @@ describe('CheckInHistoryDialogComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - declarations: [CheckInHistoryDialogComponent, DialogTemplateCoreComponent, SpinnerComponent], + declarations: [CheckInHistoryDialogComponent, DialogHeaderComponent, SpinnerComponent], - imports: [TranslateModule.forRoot(), MatIconModule, MatProgressSpinner, MatDividerModule, MatDialogModule], + imports: [HttpClientTestingModule, TranslateModule.forRoot(), MatIconModule, MatProgressSpinner], providers: [ - provideRouter([]), - provideHttpClient(), - provideHttpClientTesting(), TranslateService, DialogService, { provide: MAT_DIALOG_DATA, useValue: { keyResult: keyResult } }, diff --git a/frontend/src/app/components/keyresult-detail/keyresult-detail.component.ts b/frontend/src/app/components/keyresult-detail/keyresult-detail.component.ts index 21adfbc536..d2b5763824 100644 --- a/frontend/src/app/components/keyresult-detail/keyresult-detail.component.ts +++ b/frontend/src/app/components/keyresult-detail/keyresult-detail.component.ts @@ -4,7 +4,6 @@ import { KeyresultService } from '../../services/keyresult.service'; import { KeyResultMetric } from '../../shared/types/model/KeyResultMetric'; import { KeyResultOrdinal } from '../../shared/types/model/KeyResultOrdinal'; import { CheckInHistoryDialogComponent } from '../check-in-history-dialog/check-in-history-dialog.component'; -import { MatDialog } from '@angular/material/dialog'; import { BehaviorSubject, catchError, EMPTY, Subject, takeUntil } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; import { RefreshDataService } from '../../services/refresh-data.service'; diff --git a/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.ts b/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.ts index 9526b25676..efdfeac59c 100644 --- a/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.ts +++ b/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.ts @@ -62,7 +62,7 @@ export class KeyresultDialogComponent { deleteKeyResult() { this.dialogService - .openConfirmDialog('CONFIRMATION.DELETE.KEYRESULT') + .openConfirmDialog('CONFIRMATION.DELETE.KEY_RESULT') .afterClosed() .subscribe((result) => { if (result) { diff --git a/frontend/src/app/components/objective/objective.component.ts b/frontend/src/app/components/objective/objective.component.ts index d67984a57b..94de0b3eff 100644 --- a/frontend/src/app/components/objective/objective.component.ts +++ b/frontend/src/app/components/objective/objective.component.ts @@ -1,16 +1,15 @@ import { Component, Input, OnInit, ViewChild } from '@angular/core'; import { ObjectiveMin } from '../../shared/types/model/ObjectiveMin'; import { Router } from '@angular/router'; -import { map, ReplaySubject, take } from 'rxjs'; +import { ObjectiveFormComponent } from '../../shared/dialog/objective-dialog/objective-form.component'; +import { BehaviorSubject } from 'rxjs'; import { RefreshDataService } from '../../services/refresh-data.service'; import { ObjectiveService } from '../../services/objective.service'; import { trackByFn } from '../../shared/common'; import { KeyresultDialogComponent } from '../keyresult-dialog/keyresult-dialog.component'; import { TranslateService } from '@ngx-translate/core'; +import { GJ_REGEX_PATTERN } from '../../shared/constantLibary'; import { DialogService } from '../../services/dialog.service'; -import { ObjectiveMenuActionsService, ObjectiveMenuEntry } from '../../services/objective-menu-actions.service'; -import { State } from '../../shared/types/enums/State'; -import { MatMenuTrigger } from '@angular/material/menu'; @Component({ selector: 'app-objective-column', @@ -25,12 +24,11 @@ export class ObjectiveComponent { @ViewChild(MatMenuTrigger) trigger: MatMenuTrigger | undefined; constructor( - private readonly dialogService: DialogService, - private readonly router: Router, - private readonly refreshDataService: RefreshDataService, - private readonly objectiveService: ObjectiveService, - private readonly translate: TranslateService, - private readonly objectiveMenuActionsService: ObjectiveMenuActionsService, + private dialogService: DialogService, + private router: Router, + private refreshDataService: RefreshDataService, + private objectiveService: ObjectiveService, + private translate: TranslateService, ) {} @Input() set objective(objective: ObjectiveMin) { @@ -42,15 +40,183 @@ export class ObjectiveComponent { return this.translate.instant('INFORMATION.OBJECTIVE_STATE_TOOLTIP', { state: state }); } - redirect(menuEntry: ObjectiveMenuEntry, objectiveMin: ObjectiveMin) { - const matDialogRef = menuEntry.action(); - matDialogRef - .afterClosed() - .pipe(take(1)) - .subscribe((result) => { - this.objectiveService.getFullObjective(objectiveMin.id).subscribe((objective) => { - menuEntry.afterAction(objective, result); - this.trigger?.focus(); + formatObjectiveState(state: string): string { + const lastIndex = state.lastIndexOf('-'); + if (lastIndex !== -1) { + return state.substring(0, lastIndex).toUpperCase(); + } else { + return state.toUpperCase(); + } + } + + getStateTooltip(): string { + return this.translate.instant('INFORMATION.OBJECTIVE_STATE_TOOLTIP'); + } + + getMenu(): void { + if (this.objective$.value.state.includes('successful') || this.objective$.value.state.includes('not-successful')) { + this.menuEntries = this.getCompletedMenuActions(); + } else { + if (this.objective$.value.state === State.ONGOING) { + this.menuEntries = this.getOngoingMenuActions(); + } else { + this.menuEntries = this.getDraftMenuActions(); + } + } + } + + getOngoingMenuActions() { + return [ + ...this.getDefaultMenuActions(), + ...[ + { + displayName: 'Objective abschliessen', + action: 'complete', + dialog: { dialog: CompleteDialogComponent, data: { objectiveTitle: this.objective$.value.title } }, + }, + { + displayName: 'Objective als Draft speichern', + action: 'todraft', + dialog: { + dialog: ConfirmDialogComponent, + data: { + title: this.translate.instant('CONFIRMATION.TO_DRAFT.TITLE'), + text: this.translate.instant('CONFIRMATION.TO_DRAFT.TEXT'), + }, + }, + }, + ], + ]; + } + + getDraftMenuActions() { + const action = this.isBacklogQuarter ? 'releaseBacklog' : 'release'; + let menuEntries = { + displayName: 'Objective veröffentlichen', + action: action, + dialog: { + dialog: this.isBacklogQuarter ? ObjectiveFormComponent : ConfirmDialogComponent, + data: { + title: this.translate.instant('CONFIRMATION.RELEASE.TITLE'), + text: this.translate.instant('CONFIRMATION.RELEASE.TEXT'), + action: action, + objectiveId: this.isBacklogQuarter ? this.objective$.value.id : undefined, + }, + }, + }; + + return [...this.getDefaultMenuActions(), menuEntries]; + } + + getDefaultMenuActions() { + return [ + { + displayName: 'Objective bearbeiten', + dialog: { dialog: ObjectiveFormComponent, data: { objectiveId: this.objective$.value.id } }, + }, + { + displayName: 'Objective duplizieren', + action: 'duplicate', + dialog: { dialog: ObjectiveFormComponent, data: { objectiveId: this.objective$.value.id } }, + }, + ]; + } + + getCompletedMenuActions() { + return [ + { displayName: 'Objective wiedereröffnen', action: 'reopen' }, + { + displayName: 'Objective duplizieren', + action: 'duplicate', + dialog: { dialog: ObjectiveFormComponent, data: { objectiveId: this.objective$.value.id } }, + }, + ]; + } + + redirect(menuEntry: MenuEntry) { + if (menuEntry.dialog) { + const matDialogRef = this.dialogService.open(menuEntry.dialog.dialog, { + data: { + title: menuEntry.dialog.data.title, + action: menuEntry.action, + text: menuEntry.dialog.data.text, + objective: menuEntry.dialog.data, + objectiveTitle: menuEntry.dialog.data.objectiveTitle, + }, + ...((menuEntry.action == 'release' || menuEntry.action == 'todraft') && { width: 'auto' }), + }); + matDialogRef.afterClosed().subscribe((result) => { + this.menuButton.nativeElement.focus(); + if (result) { + this.handleDialogResult(menuEntry, result); + } + }); + } else { + this.reopenRedirect(menuEntry); + } + } + + handleDialogResult(menuEntry: MenuEntry, result: { endState: string; comment: string | null; objective: any }) { + if (menuEntry.action) { + this.objectiveService.getFullObjective(this.objective$.value.id).subscribe((objective) => { + if (menuEntry.action == 'complete') { + this.completeObjective(objective, result); + } else if (menuEntry.action == 'release') { + this.releaseObjective(objective); + } else if (menuEntry.action == 'duplicate') { + this.refreshDataService.markDataRefresh(); + } else if (menuEntry.action == 'releaseBacklog') { + this.refreshDataService.markDataRefresh(); + } else if (menuEntry.action == 'todraft') { + this.objectiveBackToDraft(objective); + } + }); + } else { + if (result?.objective) { + this.refreshDataService.markDataRefresh(); + } + } + } + + 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.isComplete = true; + this.refreshDataService.markDataRefresh(); + }); + }); + } + + releaseObjective(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(); + }); + } + + reopenRedirect(menuEntry: MenuEntry) { + if (menuEntry.action === 'reopen') { + this.objectiveService.getFullObjective(this.objective$.value.id).subscribe((objective) => { + objective.state = 'ONGOING' as State; + this.objectiveService.updateObjective(objective).subscribe(() => { + this.objectiveService.deleteCompleted(objective.id).subscribe(() => { + this.isComplete = false; + this.refreshDataService.markDataRefresh(); + }); }); }); } @@ -59,7 +225,7 @@ export class ObjectiveComponent { this.router.navigate(['details/objective', objectiveId]); } - openAddKeyResultDialog(objective: ObjectiveMin) { + openAddKeyResultDialog() { this.dialogService .open(KeyresultDialogComponent, { data: { diff --git a/frontend/src/app/services/dialog.service.spec.ts b/frontend/src/app/services/dialog.service.spec.ts index b9f540874f..a454504ed1 100644 --- a/frontend/src/app/services/dialog.service.spec.ts +++ b/frontend/src/app/services/dialog.service.spec.ts @@ -1,79 +1,19 @@ import { TestBed } from '@angular/core/testing'; import { DialogService } from './dialog.service'; -import { TranslateModule, TranslateService } from '@ngx-translate/core'; -import { MatDialog, MatDialogRef } from '@angular/material/dialog'; -import { ConfirmDialogComponent } from '../shared/dialog/confirm-dialog/confirm-dialog.component'; -import { AddEditTeamDialog } from '../team-management/add-edit-team-dialog/add-edit-team-dialog.component'; -import { provideHttpClientTesting } from '@angular/common/http/testing'; -import { provideHttpClient } from '@angular/common/http'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { TranslateCompiler, TranslateModule, TranslateService } from '@ngx-translate/core'; +import { TranslateTestingModule } from 'ngx-translate-testing'; describe('DialogService', () => { let service: DialogService; - let matDialogSpy: MatDialog; - let translateServiceSpy: TranslateService; beforeEach(() => { - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot()], - providers: [provideHttpClient(), provideHttpClientTesting(), TranslateService], - }); - matDialogSpy = TestBed.inject(MatDialog); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], providers: [TranslateService] }); service = TestBed.inject(DialogService); - translateServiceSpy = TestBed.inject(TranslateService); - jest.spyOn(matDialogSpy, 'open'); }); it('should be created', () => { expect(service).toBeTruthy(); }); - - it('should open dialog', () => { - const dialog = service.open(AddEditTeamDialog, { - data: { - aProperty: 'aValue', - }, - }); - expect(dialog).toBeInstanceOf(MatDialogRef); - expect(dialog.componentInstance).toBeInstanceOf(AddEditTeamDialog); - - expect(matDialogSpy.open).toHaveBeenCalledWith(AddEditTeamDialog, { - panelClass: service.DIALOG_PANEL_CLASS_DEFAULT, - ...service.DIALOG_CONFIG, - data: { - aProperty: 'aValue', - }, - }); - }); - - it('should open confirm dialog', () => { - const i18nData = { - team: 'the a-team', - }; - jest.spyOn(service, 'open'); - jest.spyOn(translateServiceSpy, 'instant'); - const dialog = service.openConfirmDialog('DELETE.TEAM', i18nData); - - //Call function of own service - expect(service.open).toHaveBeenCalledTimes(1); - expect(dialog).toBeInstanceOf(MatDialogRef); - expect(translateServiceSpy.instant).toHaveBeenCalledTimes(2); - expect(translateServiceSpy.instant).toHaveBeenCalledWith('DELETE.TEAM.TITLE', i18nData); - expect(translateServiceSpy.instant).toHaveBeenCalledWith('DELETE.TEAM.TEXT', i18nData); - - //Call function of angular material dialog - expect(matDialogSpy.open).toHaveBeenCalledTimes(1); - expect(dialog.componentInstance).toBeInstanceOf(ConfirmDialogComponent); - expect(dialog.componentInstance.data.title).toBe('DELETE.TEAM.TITLE'); - expect(dialog.componentInstance.data.text).toBe('DELETE.TEAM.TEXT'); - - expect(matDialogSpy.open).toHaveBeenCalledWith(ConfirmDialogComponent, { - panelClass: service.DIALOG_PANEL_CLASS_SMALL, - ...service.DIALOG_CONFIG, - data: { - title: 'DELETE.TEAM.TITLE', - text: 'DELETE.TEAM.TEXT', - }, - }); - }); }); diff --git a/frontend/src/app/services/dialog.service.ts b/frontend/src/app/services/dialog.service.ts index 964ce85571..5bfa310482 100644 --- a/frontend/src/app/services/dialog.service.ts +++ b/frontend/src/app/services/dialog.service.ts @@ -13,13 +13,9 @@ export interface ConfirmDialogData { providedIn: 'root', }) export class DialogService { - DIALOG_PANEL_CLASS_DEFAULT = 'okr-dialog-panel-default'; - DIALOG_PANEL_CLASS_SMALL = 'okr-dialog-panel-small'; - - DIALOG_CONFIG: MatDialogConfig = { - maxWidth: '100vw', // Used to override the default maxWidth of angular material dialog - restoreFocus: true, - autoFocus: 'first-tabbable', + DIALOG_CONFIG = { + panelClass: 'okr-dialog-panel', + maxWidth: '100vw', }; constructor( @@ -29,17 +25,15 @@ export class DialogService { open(component: ComponentType, config?: MatDialogConfig): MatDialogRef { return this.dialog.open(component, { - panelClass: this.DIALOG_PANEL_CLASS_DEFAULT, ...this.DIALOG_CONFIG, ...config, }); } - openConfirmDialog(translationKey: string, i18nData?: Object): MatDialogRef { - const title = this.translationService.instant(`${translationKey}.TITLE`, i18nData); - const text = this.translationService.instant(`${translationKey}.TEXT`, i18nData); + openConfirmDialog(translationKey: string) { + const title = this.translationService.instant(`${translationKey}.TITLE`); + const text = this.translationService.instant(`${translationKey}.TEXT`); return this.open(ConfirmDialogComponent, { - panelClass: this.DIALOG_PANEL_CLASS_SMALL, data: { title: title, text: text, diff --git a/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.ts b/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.ts index ccb0658056..5fb7a3c399 100644 --- a/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.ts +++ b/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; import { ConfigService } from '../../../services/config.service'; -import { BehaviorSubject, map, Observable, Subject, Subscription } from 'rxjs'; +import { map, Observable } from 'rxjs'; @Component({ selector: 'app-okr-tangram', diff --git a/frontend/src/app/shared/dialog/confirm-dialog/confirm-dialog.component.spec.ts b/frontend/src/app/shared/dialog/confirm-dialog/confirm-dialog.component.spec.ts index 22c02998c8..7ed74ba54e 100644 --- a/frontend/src/app/shared/dialog/confirm-dialog/confirm-dialog.component.spec.ts +++ b/frontend/src/app/shared/dialog/confirm-dialog/confirm-dialog.component.spec.ts @@ -11,10 +11,9 @@ import { MatInputModule } from '@angular/material/input'; import { MatRadioModule } from '@angular/material/radio'; import { ReactiveFormsModule } from '@angular/forms'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { DialogHeaderComponent } from '../../custom/dialog-header/dialog-header.component'; import { MatIconModule } from '@angular/material/icon'; import { ConfirmDialogData } from '../../../services/dialog.service'; -import { DialogTemplateCoreComponent } from '../../custom/dialog-template-core/dialog-template-core.component'; -import { MatDividerModule } from '@angular/material/divider'; const dialogRefMock = { close: jest.fn(), @@ -36,9 +35,8 @@ describe('ConfirmDialogComponent', () => { ReactiveFormsModule, TranslateModule.forRoot(), MatIconModule, - MatDividerModule, ], - declarations: [ConfirmDialogComponent, DialogTemplateCoreComponent], + declarations: [ConfirmDialogComponent, DialogHeaderComponent], providers: [ TranslateService, { provide: MAT_DIALOG_DATA, useValue: { title: '', text: '' } as ConfirmDialogData }, diff --git a/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.ts b/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.ts index 8bb93a22bd..c8267ab2c8 100644 --- a/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.ts +++ b/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.ts @@ -10,8 +10,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { State } from '../../types/enums/State'; import { ObjectiveMin } from '../../types/model/ObjectiveMin'; import { Objective } from '../../types/model/Objective'; -import { ConfirmDialogComponent } from '../confirm-dialog/confirm-dialog.component'; -import { formInputCheck, getValueFromQuery, hasFormFieldErrors, isMobileDevice } from '../../common'; +import { formInputCheck, getQuarterLabel, getValueFromQuery, hasFormFieldErrors } from '../../common'; import { ActivatedRoute } from '@angular/router'; import { GJ_REGEX_PATTERN } from '../../constantLibary'; import { TranslateService } from '@ngx-translate/core'; diff --git a/frontend/src/app/team-management/add-edit-team-dialog/add-edit-team-dialog.component.spec.ts b/frontend/src/app/team-management/add-edit-team-dialog/add-edit-team-dialog.component.spec.ts index 767eb28010..0d4a82df15 100644 --- a/frontend/src/app/team-management/add-edit-team-dialog/add-edit-team-dialog.component.spec.ts +++ b/frontend/src/app/team-management/add-edit-team-dialog/add-edit-team-dialog.component.spec.ts @@ -1,7 +1,7 @@ import { AddEditTeamDialog } from './add-edit-team-dialog.component'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HarnessLoader } from '@angular/cdk/testing'; -import { provideHttpClientTesting } from '@angular/common/http/testing'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { MatIconModule } from '@angular/material/icon'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -17,10 +17,6 @@ import { marketingTeamWriteable, teamFormObject } from '../../shared/testData'; import { Team } from '../../shared/types/model/Team'; import { TranslateService } from '@ngx-translate/core'; import { DialogService } from '../../services/dialog.service'; -import { provideRouter } from '@angular/router'; -import { provideHttpClient } from '@angular/common/http'; -import { DialogTemplateCoreComponent } from '../../shared/custom/dialog-template-core/dialog-template-core.component'; -import { MatDividerModule } from '@angular/material/divider'; const dialogRefMock = { close: jest.fn(), diff --git a/frontend/src/app/team-management/member-detail/member-detail.component.spec.ts b/frontend/src/app/team-management/member-detail/member-detail.component.spec.ts index 3ba5c57493..9173a9410a 100644 --- a/frontend/src/app/team-management/member-detail/member-detail.component.spec.ts +++ b/frontend/src/app/team-management/member-detail/member-detail.component.spec.ts @@ -17,9 +17,6 @@ import { PuzzleIconComponent } from '../../shared/custom/puzzle-icon/puzzle-icon import { CommonModule } from '@angular/common'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { DialogService } from '../../services/dialog.service'; -import { provideHttpClient } from '@angular/common/http'; -import { provideHttpClientTesting } from '@angular/common/http/testing'; -import { DialogTemplateCoreComponent } from '../../shared/custom/dialog-template-core/dialog-template-core.component'; describe('MemberDetailComponent', () => { let component: MemberDetailComponent; @@ -111,7 +108,7 @@ describe('MemberDetailComponent', () => { const userTeam = testUser.userTeamList[0]; teamServiceMock.removeUserFromTeam.mockReturnValue(of()); userServiceMock.getUserById.mockReturnValue(of(user)); - dialogServiceMock.openConfirmDialog.mockReturnValue({ + dialogServiceMock.open.mockReturnValue({ afterClosed: () => of(true), }); @@ -128,7 +125,7 @@ describe('MemberDetailComponent', () => { const userTeam = testUser.userTeamList[0]; teamServiceMock.removeUserFromTeam.mockReturnValue(of()); userServiceMock.getUserById.mockReturnValue(of(user)); - dialogServiceMock.openConfirmDialog.mockReturnValue({ + dialogServiceMock.open.mockReturnValue({ afterClosed: () => of(false), }); diff --git a/frontend/src/app/team-management/member-detail/member-detail.component.ts b/frontend/src/app/team-management/member-detail/member-detail.component.ts index 63b79efbf7..e407144f63 100644 --- a/frontend/src/app/team-management/member-detail/member-detail.component.ts +++ b/frontend/src/app/team-management/member-detail/member-detail.component.ts @@ -8,6 +8,7 @@ import { UserTeam } from '../../shared/types/model/UserTeam'; import { TranslateService } from '@ngx-translate/core'; import { MatTable } from '@angular/material/table'; import { TeamService } from '../../services/team.service'; +import { CancelDialogComponent } from '../../shared/dialog/cancel-dialog/cancel-dialog.component'; import { DialogService } from '../../services/dialog.service'; @Component({ @@ -78,12 +79,12 @@ export class MemberDetailComponent implements OnInit, OnDestroy { } removeUserFromTeam(userTeam: UserTeam, user: User) { - const i18nData = { - user: getFullNameFromUser(user), - team: userTeam.team.name, - }; this.dialogService - .openConfirmDialog('CONFIRMATION.DELETE.USER_FROM_TEAM', i18nData) + .open(CancelDialogComponent, { + data: { + dialogTitle: getFullNameFromUser(user) + ` wirklich aus Team ${userTeam.team.name} entfernen?`, + }, + }) .afterClosed() .pipe( filter((confirm) => confirm), diff --git a/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.spec.ts b/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.spec.ts index aec9651433..b8f9194361 100644 --- a/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.spec.ts +++ b/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.spec.ts @@ -95,7 +95,7 @@ describe('MemberListTableComponent', () => { teamServiceMock.removeUserFromTeam.mockReturnValue(of(null)); userServiceMock.reloadUsers.mockReturnValue(of()); userServiceMock.reloadCurrentUser.mockReturnValue(of()); - dialogService.openConfirmDialog.mockReturnValue({ + dialogService.open.mockReturnValue({ afterClosed: () => of(true), }); @@ -116,7 +116,7 @@ describe('MemberListTableComponent', () => { teamServiceMock.removeUserFromTeam.mockReturnValue(of(null)); userServiceMock.reloadUsers.mockReturnValue(of()); userServiceMock.reloadCurrentUser.mockReturnValue(of()); - dialogService.openConfirmDialog.mockReturnValue({ + dialogService.open.mockReturnValue({ afterClosed: () => of(false), }); diff --git a/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.ts b/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.ts index 1c1f587343..a9282e329f 100644 --- a/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.ts +++ b/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.ts @@ -8,6 +8,7 @@ import { UserService } from '../../../services/user.service'; import { getRouteToUserDetails } from '../../../shared/routeUtils'; import { BehaviorSubject, filter, mergeMap, Subject, takeUntil } from 'rxjs'; import { UserTeam } from '../../../shared/types/model/UserTeam'; +import { CancelDialogComponent } from '../../../shared/dialog/cancel-dialog/cancel-dialog.component'; import { DialogService } from '../../../services/dialog.service'; @Component({ @@ -56,12 +57,13 @@ export class MemberListTableComponent implements OnInit, OnDestroy { removeMemberFromTeam(entry: UserTableEntry, event: MouseEvent) { event.stopPropagation(); event.preventDefault(); - const i18nData = { - user: `${entry.firstname} ${entry.lastname}`, - team: this.selectedTeam$.value?.name, - }; + this.dialogService - .openConfirmDialog('CONFIRMATION.DELETE.USER_FROM_TEAM', i18nData) + .open(CancelDialogComponent, { + data: { + dialogTitle: `${entry.firstname} ${entry.lastname} wirklich aus Team ${this.selectedTeam$.value?.name} entfernen?`, + }, + }) .afterClosed() .pipe( filter((confirm) => confirm), diff --git a/frontend/src/app/team-management/member-list/member-list.component.spec.ts b/frontend/src/app/team-management/member-list/member-list.component.spec.ts index b54e9ee180..052ad6c0bf 100644 --- a/frontend/src/app/team-management/member-list/member-list.component.spec.ts +++ b/frontend/src/app/team-management/member-list/member-list.component.spec.ts @@ -18,7 +18,6 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { MemberListTableComponent } from './member-list-table/member-list-table.component'; import { MemberListMobileComponent } from './member-list-mobile/member-list-mobile.component'; import { DialogService } from '../../services/dialog.service'; -import { provideHttpClient } from '@angular/common/http'; const userServiceMock = { getUsers: jest.fn(), @@ -185,7 +184,7 @@ describe('MemberListComponent', () => { it('deleteTeam should trigger teamService.deleteTeam and navigate', fakeAsync(() => { routerMock.navigateByUrl.mockReturnValue(of(null)); teamServiceMock.deleteTeam.mockReturnValue(of(null)); - dialogService.openConfirmDialog.mockReturnValue({ + dialogService.open.mockReturnValue({ afterClosed: () => of(true), }); @@ -205,7 +204,7 @@ describe('MemberListComponent', () => { it('deleteTeam should not trigger teamService.deleteTeam if dialog is canceled', fakeAsync(() => { routerMock.navigateByUrl.mockReturnValue(of(null)); teamServiceMock.deleteTeam.mockReturnValue(of(null)); - dialogService.openConfirmDialog.mockReturnValue({ + dialogService.open.mockReturnValue({ afterClosed: () => of(false), }); diff --git a/frontend/src/app/team-management/member-list/member-list.component.ts b/frontend/src/app/team-management/member-list/member-list.component.ts index 1ae5ba4865..264af1dce5 100644 --- a/frontend/src/app/team-management/member-list/member-list.component.ts +++ b/frontend/src/app/team-management/member-list/member-list.component.ts @@ -84,12 +84,13 @@ export class MemberListComponent implements OnInit, OnDestroy, AfterViewInit { } deleteTeam(selectedTeam: Team) { - const data = { - team: selectedTeam.name, - }; - this.dialogService - .openConfirmDialog('CONFIRMATION.DELETE.TEAM', data) + .open(CancelDialogComponent, { + data: { + dialogTitle: selectedTeam.name + ' wirklich löschen?', + dialogText: 'Soll das Team und dessen OKRs wirklich gelöscht werden?', + }, + }) .afterClosed() .pipe( filter((confirm) => confirm), diff --git a/frontend/src/assets/i18n/de.json b/frontend/src/assets/i18n/de.json index be9c8d61a4..fb5e054302 100644 --- a/frontend/src/assets/i18n/de.json +++ b/frontend/src/assets/i18n/de.json @@ -65,6 +65,38 @@ } } }, + "CONFIRMATION": { + "DRAFT_CREATE": { + "TITLE": "Check-in im Draft-Status", + "TEXT": "Dein Objective befindet sich noch im DRAFT Status. Möchtest du das Check-in trotzdem erfassen?" + }, + "RELEASE": { + "TITLE": "Objective veröffentlichen", + "TEXT": "Soll dieses Objective veröffentlicht werden?" + }, + "TO_DRAFT": { + "TITLE": "Objective als Draft speichern", + "TEXT": "Soll dieses Objective als Draft gespeichert werden?" + }, + "DELETE": { + "ACTION":{ + "TITLE": "Löschen bestätigen", + "TEXT": "Möchtest du die Action wirklich löschen?" + }, + "TEAM":{ + "TITLE": "Löschen bestätigen", + "TEXT": "Möchtest du dieses Team wirklich löschen? Zugehörige Objectives werden dadurch in allen Quartalen ebenfalls gelöscht!" + }, + "OBJECTIVE":{ + "TITLE": "Objective löschen", + "TEXT": "Möchtest du dieses Objective wirklich löschen? Zugehörige Key Results werden dadurch ebenfalls gelöscht!" + }, + "KEYRESULT":{ + "TITLE": "Key Result löschen", + "TEXT": "Möchtest du dieses Key Result wirklich löschen? Zugehörige Check-ins werden dadurch ebenfalls gelöscht!" + } + } + }, "ERROR": { "UNAUTHORIZED": "Du bist nicht autorisiert, um das Objekt mit der Id {1} zu öffnen.", "NOT_FOUND": "Das Objekt '{0}' mit der Id {1} konnte nicht gefunden werden.", diff --git a/frontend/src/style/custom_angular.components.scss b/frontend/src/style/custom_angular.components.scss index 46e8b82be5..3e65e2d3b5 100644 --- a/frontend/src/style/custom_angular.components.scss +++ b/frontend/src/style/custom_angular.components.scss @@ -48,6 +48,15 @@ display: none !important; } +.mat-mdc-dialog-surface { + padding: 1rem 0 1rem 0; +} + +mat-dialog-content, +mat-dialog-actions { + padding: 0 1.62rem 0 1.62rem !important; +} + //Offset for top bar .cdk-overlay-backdrop.cdk-overlay-dark-backdrop.cdk-overlay-backdrop-showing { margin-top: $top-bar-height; diff --git a/frontend/src/style/styles.scss b/frontend/src/style/styles.scss index 6ebff4ac77..bfd8c3f7df 100644 --- a/frontend/src/style/styles.scss +++ b/frontend/src/style/styles.scss @@ -348,53 +348,7 @@ table.okr-table { } .okr-dialog-panel { - margin-top: $top-bar-height; - max-height: calc(100vh - $top-bar-height); @extend .col-12; -} -.okr-dialog-panel-default { - @extend .okr-dialog-panel; - @extend .col-sm-8; @extend .col-md-6; - @extend .col-lg-5; - @extend .col-xxl-4; - @include media-breakpoint-down(sm) { - height: 100%; - } -} - -.okr-dialog-panel-small { - @extend .okr-dialog-panel; - @extend .col-sm-8; - @extend .col-md-6; - @extend .col-lg-5; - @extend .col-xl-4; - @extend .col-xxl-3; -} - -.okr-form-container { - @extend .container-fluid; -} - -.okr-form-row { - @extend .row; -} - -.okr-form-col { - @extend .col-12; -} - -.okr-form-label { - color: black; - @extend .py-1; -} - -// Is used to style the input fields in the OKR form globally -.okr-form-input { - @extend .okr-form-col; -} - -.okr-form-label-input-container { - @extend .py-1; } From 363ac9d866af35f1768f92645e73116c96a2e285 Mon Sep 17 00:00:00 2001 From: nevio18324 <141240169+nevio18324@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:48:49 +0100 Subject: [PATCH 14/28] create tests for dialog-service (#1112) --- .../src/app/services/dialog.service.spec.ts | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/services/dialog.service.spec.ts b/frontend/src/app/services/dialog.service.spec.ts index a454504ed1..16b4888d16 100644 --- a/frontend/src/app/services/dialog.service.spec.ts +++ b/frontend/src/app/services/dialog.service.spec.ts @@ -1,9 +1,10 @@ import { TestBed } from '@angular/core/testing'; import { DialogService } from './dialog.service'; -import { HttpClientTestingModule } from '@angular/common/http/testing'; -import { TranslateCompiler, TranslateModule, TranslateService } from '@ngx-translate/core'; -import { TranslateTestingModule } from 'ngx-translate-testing'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { MatDialogRef } from '@angular/material/dialog'; +import { ConfirmDialogComponent } from '../shared/dialog/confirm-dialog/confirm-dialog.component'; +import { TeamComponent } from '../components/team/team.component'; describe('DialogService', () => { let service: DialogService; @@ -16,4 +17,22 @@ describe('DialogService', () => { it('should be created', () => { expect(service).toBeTruthy(); }); + + it('should open dialog', () => { + const dialog = service.open(TeamComponent); + expect(dialog).toBeInstanceOf(MatDialogRef); + expect(dialog._containerInstance._config.panelClass).toEqual(service.DIALOG_CONFIG.panelClass); + expect(dialog._containerInstance._config.maxWidth).toEqual(service.DIALOG_CONFIG.maxWidth); + expect(dialog.componentInstance).toBeInstanceOf(TeamComponent); + }); + + it('should open confirm dialog', () => { + jest.spyOn(service, 'open'); + const dialog = service.openConfirmDialog('DELETE.ACTION'); + expect(service.open).toHaveBeenCalledTimes(1); + expect(dialog).toBeInstanceOf(MatDialogRef); + expect(dialog.componentInstance).toBeInstanceOf(ConfirmDialogComponent); + expect(dialog.componentInstance.data.title).toBe('DELETE.ACTION.TITLE'); + expect(dialog.componentInstance.data.text).toBe('DELETE.ACTION.TEXT'); + }); }); From 62e7adad28fcc8691915c5c32d4a9f40dd560365 Mon Sep 17 00:00:00 2001 From: Yanick Minder <79108296+kcinay055679@users.noreply.github.com> Date: Mon, 4 Nov 2024 14:50:57 +0100 Subject: [PATCH 15/28] Get current quarter from backend (#1039) * 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 Co-authored-by: Jannik Pulfer Co-authored-by: GitHub Actions --- .../key-result-form.component.spec.ts | 3 -- .../keyresult-dialog.component.spec.ts | 5 --- .../objective-form.component.html | 33 +++++++++---------- .../objective-form.component.ts | 23 ++----------- 4 files changed, 17 insertions(+), 47 deletions(-) diff --git a/frontend/src/app/components/key-result-form/key-result-form.component.spec.ts b/frontend/src/app/components/key-result-form/key-result-form.component.spec.ts index 3e29d0ee5a..ead21fc765 100644 --- a/frontend/src/app/components/key-result-form/key-result-form.component.spec.ts +++ b/frontend/src/app/components/key-result-form/key-result-form.component.spec.ts @@ -27,9 +27,6 @@ import { KeyResultOrdinal } from '../../shared/types/model/KeyResultOrdinal'; import { TranslateTestingModule } from 'ngx-translate-testing'; // @ts-ignore import * as de from '../../../assets/i18n/de.json'; -import { provideRouter } from '@angular/router'; -import { provideHttpClient } from '@angular/common/http'; -import { DialogTemplateCoreComponent } from '../../shared/custom/dialog-template-core/dialog-template-core.component'; import { Quarter } from '../../shared/types/model/Quarter'; describe('KeyResultFormComponent', () => { diff --git a/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.spec.ts b/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.spec.ts index e13b93a55d..16cc546d64 100644 --- a/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.spec.ts +++ b/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.spec.ts @@ -22,11 +22,6 @@ 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 { provideRouter } from '@angular/router'; -import { provideHttpClient } from '@angular/common/http'; -import { provideHttpClientTesting } from '@angular/common/http/testing'; -import { MatDividerModule } from '@angular/material/divider'; -import { DialogTemplateCoreComponent } from '../../shared/custom/dialog-template-core/dialog-template-core.component'; import { Quarter } from '../../shared/types/model/Quarter'; describe('KeyresultDialogComponent', () => { diff --git a/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.html b/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.html index 8479d497d8..b728983884 100644 --- a/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.html +++ b/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.html @@ -32,24 +32,21 @@ -
-
-
- -
- -
+
+
+ +
diff --git a/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.ts b/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.ts index c8267ab2c8..9875795967 100644 --- a/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.ts +++ b/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.ts @@ -10,7 +10,8 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { State } from '../../types/enums/State'; import { ObjectiveMin } from '../../types/model/ObjectiveMin'; import { Objective } from '../../types/model/Objective'; -import { formInputCheck, getQuarterLabel, getValueFromQuery, hasFormFieldErrors } from '../../common'; +import { ConfirmDialogComponent } from '../confirm-dialog/confirm-dialog.component'; +import { formInputCheck, getValueFromQuery, hasFormFieldErrors, isMobileDevice } from '../../common'; import { ActivatedRoute } from '@angular/router'; import { GJ_REGEX_PATTERN } from '../../constantLibary'; import { TranslateService } from '@ngx-translate/core'; @@ -216,24 +217,4 @@ export class ObjectiveFormComponent implements OnInit, OnDestroy { isBacklogQuarter(label: string) { return GJ_REGEX_PATTERN.test(label); } - - getDialogTitle(teamName: string): string { - if (this.data.action === 'duplicate') { - return `Objective von ${teamName} duplizieren`; - } - - if (this.data.action === 'releaseBacklog') { - return 'Objective veröffentlichen'; - } - - if (!this.data.objective.objectiveId) { - return `Objective für ${teamName} erfassen`; - } - - if (this.data.objective.objectiveId && this.data.action !== 'releaseBacklog') { - return `Objective von ${teamName} bearbeiten`; - } - - return ''; - } } From f87b588aeac0158e5584c6d7438738c9a534c0e0 Mon Sep 17 00:00:00 2001 From: Yanick Minder <79108296+kcinay055679@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:51:13 +0100 Subject: [PATCH 16/28] Fix/fix git history (#1125) * fix history * fix hist --- .run/OkrApplication-local-prod-debug.run.xml | 17 ----------------- .../resources/application-staging.properties | 6 +++--- 2 files changed, 3 insertions(+), 20 deletions(-) delete mode 100755 .run/OkrApplication-local-prod-debug.run.xml diff --git a/.run/OkrApplication-local-prod-debug.run.xml b/.run/OkrApplication-local-prod-debug.run.xml deleted file mode 100755 index 15ae63f4ef..0000000000 --- a/.run/OkrApplication-local-prod-debug.run.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/backend/src/main/resources/application-staging.properties b/backend/src/main/resources/application-staging.properties index 31ce92a3c2..effd67d65a 100644 --- a/backend/src/main/resources/application-staging.properties +++ b/backend/src/main/resources/application-staging.properties @@ -4,7 +4,7 @@ logging.level.org.springframework=debug connect.src=http://localhost:8544 http://localhost:8545 -hibernate.connection.url=jdbc:postgresql://okr-dev-db:5432/okr +hibernate.connection.url=jdbc:postgresql://localhost:5432/okr hibernate.connection.username=user hibernate.connection.password=pwd hibernate.multiTenancy=SCHEMA @@ -16,7 +16,7 @@ okr.datasource.driver-class-name=org.postgresql.Driver okr.user.champion.usernames=peggimann # pitc -okr.tenants.pitc.datasource.url=jdbc:postgresql://okr-dev-db:5432/okr +okr.tenants.pitc.datasource.url=jdbc:postgresql://localhost:5432/okr okr.tenants.pitc.datasource.username=user okr.tenants.pitc.datasource.password=pwd okr.tenants.pitc.datasource.schema=okr_pitc @@ -27,7 +27,7 @@ okr.tenants.pitc.security.oauth2.frontend.client-id=pitc_okr_staging # acme -okr.tenants.acme.datasource.url=jdbc:postgresql://okr-dev-db:5432/okr +okr.tenants.acme.datasource.url=jdbc:postgresql://localhost:5432/okr okr.tenants.acme.datasource.username=user okr.tenants.acme.datasource.password=pwd okr.tenants.acme.datasource.schema=okr_acme From 17124c94e6bd3abb1c9d0612c6ab1024a2930ed0 Mon Sep 17 00:00:00 2001 From: Yanick Minder <79108296+kcinay055679@users.noreply.github.com> Date: Wed, 6 Nov 2024 11:51:55 +0100 Subject: [PATCH 17/28] refactor styles of dialogs (#1072) * add jar debug dev tools only on profile * change log levels * try to fix autorestart of spring * rename intelij config and change log level of spring to debug in staging config * rename folder * use external profile to disable formatter * remove backend/pom.xml from branch * refactor styles of dialogs * remove useless tabindex * refactor styling of dialog-content and dialog-actions * refactor dialog header * clean up * fix invite members test * change default width of dialog * set cypress viewport * remove it.only from cy tests * use diffrent classes for default and small dialogs * remove useless config * clean up styling * remove scroll-shaddow * change height sizing strategie * refactor styling of keyresult edit component * introduce dialog-template-core-component * create base template for dialogs * align close button * comment in dialog component * fix scrolling of dialog * refactor kr-type-form * finish styling of kr-type select * fix scrolling by setting height of action buttons * clean up dialog content size * clean up styles.scss * refactor styles * refactor styles of generic component * move core component to shared module * fix design because of scrollbar * change keyresult type tabs to butotns * delete cancel dialog and refactor related files * refactor confirm dialog component to use template dialog core * refactor styling * refactor style of okr-label * refactor example dialog * refactor objective form component to use template dialog core * refactor objective form dialog * refactor dialog width * refactor keyresult component * fix responsive dialog * refactor objective complete dialog * clean up * refactor objective form component * minder out * fix objective form component * use priority to fetch logos * refactor dialog history compoennt * add spinner to dialog core * refactor dialog history component * refactor check-in componentn * refactor metric check in component * clean up keyresult dialog * clean up * fix kr type component * finish dialog refactoring * remove header component * refactor css classes * refactor styling * insert okr-form-label-input-container * fix dialog service tests * fix jest of objective form compoennt * fix tests of keyresult form * fix pom * fix tests of add-edit team dialog * fix tests keyresult-dialog tests * fix tests of complete dialog * fix jest tests * readd cancel button for check-in create * fix check-in e2e tests * fix e2e tests * remove only from cypress tests * fix teammanagement e2e test * fix duplicate scorring * clean up check-in tests * fix objective duplicate tests * clean up * clean up styles * create a dialog-data-show class * fix check in metric * fix keyresult type * clean up * implement todo --------- Co-authored-by: peggimann --- .../resources/application-staging.properties | 4 +- frontend/cypress/e2e/checkIn.cy.ts | 2 +- frontend/cypress/e2e/objective.cy.ts | 2 +- .../action-plan/action-plan.component.html | 2 +- .../application-top-bar.component.html | 13 +--- .../check-in-history-dialog.component.html | 5 +- .../check-in-history-dialog.component.spec.ts | 12 +++- .../check-in-form-metric.component.html | 2 +- .../confidence/confidence.component.html | 2 +- .../key-result-form.component.spec.ts | 3 + .../keyresult-dialog.component.spec.ts | 5 ++ .../keyresult-dialog.component.ts | 2 +- .../src/app/services/dialog.service.spec.ts | 61 ++++++++++++++++--- frontend/src/app/services/dialog.service.ts | 17 ++++-- .../okr-tangram/okr-tangram.component.html | 2 +- .../confirm-dialog.component.spec.ts | 6 +- .../objective-form.component.html | 33 +++++----- .../objective-form.component.ts | 20 ++++++ frontend/src/app/shared/shared.module.ts | 1 - .../add-edit-team-dialog.component.spec.ts | 6 +- .../member-detail.component.spec.ts | 7 ++- .../member-detail/member-detail.component.ts | 11 ++-- .../member-list-table.component.spec.ts | 4 +- .../member-list-table.component.ts | 12 ++-- .../member-list/member-list.component.spec.ts | 5 +- .../member-list/member-list.component.ts | 11 ++-- frontend/src/assets/i18n/de.json | 8 ++- .../src/style/custom_angular.components.scss | 9 --- frontend/src/style/styles.scss | 54 +++++++++++++--- 29 files changed, 218 insertions(+), 103 deletions(-) diff --git a/backend/src/main/resources/application-staging.properties b/backend/src/main/resources/application-staging.properties index effd67d65a..38e4a47571 100644 --- a/backend/src/main/resources/application-staging.properties +++ b/backend/src/main/resources/application-staging.properties @@ -1,5 +1,7 @@ # logging level for staging -logging.level.org.springframework=debug +logging.level.ch.puzzle.okr=DEBUG +#logging.level.org.flywaydb.core=DEBUG + connect.src=http://localhost:8544 http://localhost:8545 diff --git a/frontend/cypress/e2e/checkIn.cy.ts b/frontend/cypress/e2e/checkIn.cy.ts index 6024396ae2..3b4b749edc 100644 --- a/frontend/cypress/e2e/checkIn.cy.ts +++ b/frontend/cypress/e2e/checkIn.cy.ts @@ -374,7 +374,7 @@ describe('OKR Check-in e2e tests', () => { cy.wait('@getKeyResultsAfterSave'); cy.getByTestId('add-check-in').first().click(); - cy.contains('Letzter Wert').siblings('div').contains('10%'); + cy.contains('Letzter Wert').siblings('div').contains('10 %'); }); }); }); diff --git a/frontend/cypress/e2e/objective.cy.ts b/frontend/cypress/e2e/objective.cy.ts index 34b4611d30..2e0b3cb305 100644 --- a/frontend/cypress/e2e/objective.cy.ts +++ b/frontend/cypress/e2e/objective.cy.ts @@ -30,7 +30,7 @@ describe('OKR Objective e2e tests', () => { .click(); cy.contains('Objective veröffentlichen'); cy.contains('Soll dieses Objective veröffentlicht werden?'); - cy.getByTestId('confirmYes').click(); + cy.getByTestId('confirm-yes').click(); cy.getByTestId('objective') .filter(':contains(A objective in state draft)') .last() diff --git a/frontend/src/app/components/action-plan/action-plan.component.html b/frontend/src/app/components/action-plan/action-plan.component.html index 68388cea32..0dc3ac9c45 100644 --- a/frontend/src/app/components/action-plan/action-plan.component.html +++ b/frontend/src/app/components/action-plan/action-plan.component.html @@ -42,7 +42,7 @@
-
+
+
diff --git a/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.spec.ts b/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.spec.ts index 5ed4650bd6..ee75865c64 100644 --- a/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.spec.ts +++ b/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.spec.ts @@ -7,10 +7,13 @@ import { checkInMetric, checkInMetricWriteableFalse, keyResult } from '../../sha import { By } from '@angular/platform-browser'; import { DialogService } from '../../services/dialog.service'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; -import { DialogHeaderComponent } from '../../shared/custom/dialog-header/dialog-header.component'; import { MatIconModule } from '@angular/material/icon'; import { SpinnerComponent } from '../../shared/custom/spinner/spinner.component'; import { MatProgressSpinner } from '@angular/material/progress-spinner'; +import { provideRouter } from '@angular/router'; +import { provideHttpClient } from '@angular/common/http'; +import { DialogTemplateCoreComponent } from '../../shared/custom/dialog-template-core/dialog-template-core.component'; +import { MatDividerModule } from '@angular/material/divider'; const checkInService = { getAllCheckInOfKeyResult: jest.fn(), @@ -22,10 +25,13 @@ describe('CheckInHistoryDialogComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - declarations: [CheckInHistoryDialogComponent, DialogHeaderComponent, SpinnerComponent], + declarations: [CheckInHistoryDialogComponent, DialogTemplateCoreComponent, SpinnerComponent], - imports: [HttpClientTestingModule, TranslateModule.forRoot(), MatIconModule, MatProgressSpinner], + imports: [TranslateModule.forRoot(), MatIconModule, MatProgressSpinner, MatDividerModule, MatDialogModule], providers: [ + provideRouter([]), + provideHttpClient(), + provideHttpClientTesting(), TranslateService, DialogService, { provide: MAT_DIALOG_DATA, useValue: { keyResult: keyResult } }, diff --git a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.html b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.html index f66dfb6ea5..3c796f384f 100644 --- a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.html +++ b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.html @@ -27,7 +27,7 @@

Letzter Wert

-
{{ checkIn.value }}{{ generateUnitLabel() }}
+
{{ checkIn.value }} {{ generateUnitLabel() }}
diff --git a/frontend/src/app/components/confidence/confidence.component.html b/frontend/src/app/components/confidence/confidence.component.html index fa587720f9..87c300b8aa 100644 --- a/frontend/src/app/components/confidence/confidence.component.html +++ b/frontend/src/app/components/confidence/confidence.component.html @@ -1,4 +1,4 @@ - diff --git a/frontend/src/app/components/key-result-form/key-result-form.component.spec.ts b/frontend/src/app/components/key-result-form/key-result-form.component.spec.ts index ead21fc765..3e29d0ee5a 100644 --- a/frontend/src/app/components/key-result-form/key-result-form.component.spec.ts +++ b/frontend/src/app/components/key-result-form/key-result-form.component.spec.ts @@ -27,6 +27,9 @@ import { KeyResultOrdinal } from '../../shared/types/model/KeyResultOrdinal'; import { TranslateTestingModule } from 'ngx-translate-testing'; // @ts-ignore import * as de from '../../../assets/i18n/de.json'; +import { provideRouter } from '@angular/router'; +import { provideHttpClient } from '@angular/common/http'; +import { DialogTemplateCoreComponent } from '../../shared/custom/dialog-template-core/dialog-template-core.component'; import { Quarter } from '../../shared/types/model/Quarter'; describe('KeyResultFormComponent', () => { diff --git a/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.spec.ts b/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.spec.ts index 16cc546d64..e13b93a55d 100644 --- a/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.spec.ts +++ b/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.spec.ts @@ -22,6 +22,11 @@ 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 { provideRouter } from '@angular/router'; +import { provideHttpClient } from '@angular/common/http'; +import { provideHttpClientTesting } from '@angular/common/http/testing'; +import { MatDividerModule } from '@angular/material/divider'; +import { DialogTemplateCoreComponent } from '../../shared/custom/dialog-template-core/dialog-template-core.component'; import { Quarter } from '../../shared/types/model/Quarter'; describe('KeyresultDialogComponent', () => { diff --git a/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.ts b/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.ts index efdfeac59c..9526b25676 100644 --- a/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.ts +++ b/frontend/src/app/components/keyresult-dialog/keyresult-dialog.component.ts @@ -62,7 +62,7 @@ export class KeyresultDialogComponent { deleteKeyResult() { this.dialogService - .openConfirmDialog('CONFIRMATION.DELETE.KEY_RESULT') + .openConfirmDialog('CONFIRMATION.DELETE.KEYRESULT') .afterClosed() .subscribe((result) => { if (result) { diff --git a/frontend/src/app/services/dialog.service.spec.ts b/frontend/src/app/services/dialog.service.spec.ts index 16b4888d16..b9f540874f 100644 --- a/frontend/src/app/services/dialog.service.spec.ts +++ b/frontend/src/app/services/dialog.service.spec.ts @@ -2,16 +2,26 @@ import { TestBed } from '@angular/core/testing'; import { DialogService } from './dialog.service'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; -import { MatDialogRef } from '@angular/material/dialog'; +import { MatDialog, MatDialogRef } from '@angular/material/dialog'; import { ConfirmDialogComponent } from '../shared/dialog/confirm-dialog/confirm-dialog.component'; -import { TeamComponent } from '../components/team/team.component'; +import { AddEditTeamDialog } from '../team-management/add-edit-team-dialog/add-edit-team-dialog.component'; +import { provideHttpClientTesting } from '@angular/common/http/testing'; +import { provideHttpClient } from '@angular/common/http'; describe('DialogService', () => { let service: DialogService; + let matDialogSpy: MatDialog; + let translateServiceSpy: TranslateService; beforeEach(() => { - TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], providers: [TranslateService] }); + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + providers: [provideHttpClient(), provideHttpClientTesting(), TranslateService], + }); + matDialogSpy = TestBed.inject(MatDialog); service = TestBed.inject(DialogService); + translateServiceSpy = TestBed.inject(TranslateService); + jest.spyOn(matDialogSpy, 'open'); }); it('should be created', () => { @@ -19,20 +29,51 @@ describe('DialogService', () => { }); it('should open dialog', () => { - const dialog = service.open(TeamComponent); + const dialog = service.open(AddEditTeamDialog, { + data: { + aProperty: 'aValue', + }, + }); expect(dialog).toBeInstanceOf(MatDialogRef); - expect(dialog._containerInstance._config.panelClass).toEqual(service.DIALOG_CONFIG.panelClass); - expect(dialog._containerInstance._config.maxWidth).toEqual(service.DIALOG_CONFIG.maxWidth); - expect(dialog.componentInstance).toBeInstanceOf(TeamComponent); + expect(dialog.componentInstance).toBeInstanceOf(AddEditTeamDialog); + + expect(matDialogSpy.open).toHaveBeenCalledWith(AddEditTeamDialog, { + panelClass: service.DIALOG_PANEL_CLASS_DEFAULT, + ...service.DIALOG_CONFIG, + data: { + aProperty: 'aValue', + }, + }); }); it('should open confirm dialog', () => { + const i18nData = { + team: 'the a-team', + }; jest.spyOn(service, 'open'); - const dialog = service.openConfirmDialog('DELETE.ACTION'); + jest.spyOn(translateServiceSpy, 'instant'); + const dialog = service.openConfirmDialog('DELETE.TEAM', i18nData); + + //Call function of own service expect(service.open).toHaveBeenCalledTimes(1); expect(dialog).toBeInstanceOf(MatDialogRef); + expect(translateServiceSpy.instant).toHaveBeenCalledTimes(2); + expect(translateServiceSpy.instant).toHaveBeenCalledWith('DELETE.TEAM.TITLE', i18nData); + expect(translateServiceSpy.instant).toHaveBeenCalledWith('DELETE.TEAM.TEXT', i18nData); + + //Call function of angular material dialog + expect(matDialogSpy.open).toHaveBeenCalledTimes(1); expect(dialog.componentInstance).toBeInstanceOf(ConfirmDialogComponent); - expect(dialog.componentInstance.data.title).toBe('DELETE.ACTION.TITLE'); - expect(dialog.componentInstance.data.text).toBe('DELETE.ACTION.TEXT'); + expect(dialog.componentInstance.data.title).toBe('DELETE.TEAM.TITLE'); + expect(dialog.componentInstance.data.text).toBe('DELETE.TEAM.TEXT'); + + expect(matDialogSpy.open).toHaveBeenCalledWith(ConfirmDialogComponent, { + panelClass: service.DIALOG_PANEL_CLASS_SMALL, + ...service.DIALOG_CONFIG, + data: { + title: 'DELETE.TEAM.TITLE', + text: 'DELETE.TEAM.TEXT', + }, + }); }); }); diff --git a/frontend/src/app/services/dialog.service.ts b/frontend/src/app/services/dialog.service.ts index 5bfa310482..a1236133ea 100644 --- a/frontend/src/app/services/dialog.service.ts +++ b/frontend/src/app/services/dialog.service.ts @@ -13,9 +13,12 @@ export interface ConfirmDialogData { providedIn: 'root', }) export class DialogService { - DIALOG_CONFIG = { - panelClass: 'okr-dialog-panel', - maxWidth: '100vw', + DIALOG_PANEL_CLASS_DEFAULT = 'okr-dialog-panel-default'; + DIALOG_PANEL_CLASS_SMALL = 'okr-dialog-panel-small'; + + DIALOG_CONFIG: MatDialogConfig = { + maxWidth: '100vw', // Used to override the default maxWidth of angular material dialog + autoFocus: 'first-tabbable', }; constructor( @@ -25,15 +28,17 @@ export class DialogService { open(component: ComponentType, config?: MatDialogConfig): MatDialogRef { return this.dialog.open(component, { + panelClass: this.DIALOG_PANEL_CLASS_DEFAULT, ...this.DIALOG_CONFIG, ...config, }); } - openConfirmDialog(translationKey: string) { - const title = this.translationService.instant(`${translationKey}.TITLE`); - const text = this.translationService.instant(`${translationKey}.TEXT`); + openConfirmDialog(translationKey: string, i18nData?: Object): MatDialogRef { + const title = this.translationService.instant(`${translationKey}.TITLE`, i18nData); + const text = this.translationService.instant(`${translationKey}.TEXT`, i18nData); return this.open(ConfirmDialogComponent, { + panelClass: this.DIALOG_PANEL_CLASS_SMALL, data: { title: title, text: text, diff --git a/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.html b/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.html index abd7776d79..92bb32f252 100644 --- a/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.html +++ b/frontend/src/app/shared/custom/okr-tangram/okr-tangram.component.html @@ -1 +1 @@ -okr-logo +okr-logo diff --git a/frontend/src/app/shared/dialog/confirm-dialog/confirm-dialog.component.spec.ts b/frontend/src/app/shared/dialog/confirm-dialog/confirm-dialog.component.spec.ts index 7ed74ba54e..22c02998c8 100644 --- a/frontend/src/app/shared/dialog/confirm-dialog/confirm-dialog.component.spec.ts +++ b/frontend/src/app/shared/dialog/confirm-dialog/confirm-dialog.component.spec.ts @@ -11,9 +11,10 @@ import { MatInputModule } from '@angular/material/input'; import { MatRadioModule } from '@angular/material/radio'; import { ReactiveFormsModule } from '@angular/forms'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; -import { DialogHeaderComponent } from '../../custom/dialog-header/dialog-header.component'; import { MatIconModule } from '@angular/material/icon'; import { ConfirmDialogData } from '../../../services/dialog.service'; +import { DialogTemplateCoreComponent } from '../../custom/dialog-template-core/dialog-template-core.component'; +import { MatDividerModule } from '@angular/material/divider'; const dialogRefMock = { close: jest.fn(), @@ -35,8 +36,9 @@ describe('ConfirmDialogComponent', () => { ReactiveFormsModule, TranslateModule.forRoot(), MatIconModule, + MatDividerModule, ], - declarations: [ConfirmDialogComponent, DialogHeaderComponent], + declarations: [ConfirmDialogComponent, DialogTemplateCoreComponent], providers: [ TranslateService, { provide: MAT_DIALOG_DATA, useValue: { title: '', text: '' } as ConfirmDialogData }, diff --git a/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.html b/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.html index b728983884..8479d497d8 100644 --- a/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.html +++ b/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.html @@ -32,21 +32,24 @@
-
-
- - +
+
+
+ +
+ +
diff --git a/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.ts b/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.ts index 9875795967..8bb93a22bd 100644 --- a/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.ts +++ b/frontend/src/app/shared/dialog/objective-dialog/objective-form.component.ts @@ -217,4 +217,24 @@ export class ObjectiveFormComponent implements OnInit, OnDestroy { isBacklogQuarter(label: string) { return GJ_REGEX_PATTERN.test(label); } + + getDialogTitle(teamName: string): string { + if (this.data.action === 'duplicate') { + return `Objective von ${teamName} duplizieren`; + } + + if (this.data.action === 'releaseBacklog') { + return 'Objective veröffentlichen'; + } + + if (!this.data.objective.objectiveId) { + return `Objective für ${teamName} erfassen`; + } + + if (this.data.objective.objectiveId && this.data.action !== 'releaseBacklog') { + return `Objective von ${teamName} bearbeiten`; + } + + return ''; + } } diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index 783ed85b71..1ed7295b52 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -25,7 +25,6 @@ import { SpinnerComponent } from './custom/spinner/spinner.component'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { DialogTemplateCoreComponent } from './custom/dialog-template-core/dialog-template-core.component'; import { MatDividerModule } from '@angular/material/divider'; -import { UnitLabelTransformationPipe } from './pipes/unit-label-transformation/unit-label-transformation.pipe'; @NgModule({ declarations: [ diff --git a/frontend/src/app/team-management/add-edit-team-dialog/add-edit-team-dialog.component.spec.ts b/frontend/src/app/team-management/add-edit-team-dialog/add-edit-team-dialog.component.spec.ts index 0d4a82df15..767eb28010 100644 --- a/frontend/src/app/team-management/add-edit-team-dialog/add-edit-team-dialog.component.spec.ts +++ b/frontend/src/app/team-management/add-edit-team-dialog/add-edit-team-dialog.component.spec.ts @@ -1,7 +1,7 @@ import { AddEditTeamDialog } from './add-edit-team-dialog.component'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HarnessLoader } from '@angular/cdk/testing'; -import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { provideHttpClientTesting } from '@angular/common/http/testing'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { MatIconModule } from '@angular/material/icon'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -17,6 +17,10 @@ import { marketingTeamWriteable, teamFormObject } from '../../shared/testData'; import { Team } from '../../shared/types/model/Team'; import { TranslateService } from '@ngx-translate/core'; import { DialogService } from '../../services/dialog.service'; +import { provideRouter } from '@angular/router'; +import { provideHttpClient } from '@angular/common/http'; +import { DialogTemplateCoreComponent } from '../../shared/custom/dialog-template-core/dialog-template-core.component'; +import { MatDividerModule } from '@angular/material/divider'; const dialogRefMock = { close: jest.fn(), diff --git a/frontend/src/app/team-management/member-detail/member-detail.component.spec.ts b/frontend/src/app/team-management/member-detail/member-detail.component.spec.ts index 9173a9410a..3ba5c57493 100644 --- a/frontend/src/app/team-management/member-detail/member-detail.component.spec.ts +++ b/frontend/src/app/team-management/member-detail/member-detail.component.spec.ts @@ -17,6 +17,9 @@ import { PuzzleIconComponent } from '../../shared/custom/puzzle-icon/puzzle-icon import { CommonModule } from '@angular/common'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { DialogService } from '../../services/dialog.service'; +import { provideHttpClient } from '@angular/common/http'; +import { provideHttpClientTesting } from '@angular/common/http/testing'; +import { DialogTemplateCoreComponent } from '../../shared/custom/dialog-template-core/dialog-template-core.component'; describe('MemberDetailComponent', () => { let component: MemberDetailComponent; @@ -108,7 +111,7 @@ describe('MemberDetailComponent', () => { const userTeam = testUser.userTeamList[0]; teamServiceMock.removeUserFromTeam.mockReturnValue(of()); userServiceMock.getUserById.mockReturnValue(of(user)); - dialogServiceMock.open.mockReturnValue({ + dialogServiceMock.openConfirmDialog.mockReturnValue({ afterClosed: () => of(true), }); @@ -125,7 +128,7 @@ describe('MemberDetailComponent', () => { const userTeam = testUser.userTeamList[0]; teamServiceMock.removeUserFromTeam.mockReturnValue(of()); userServiceMock.getUserById.mockReturnValue(of(user)); - dialogServiceMock.open.mockReturnValue({ + dialogServiceMock.openConfirmDialog.mockReturnValue({ afterClosed: () => of(false), }); diff --git a/frontend/src/app/team-management/member-detail/member-detail.component.ts b/frontend/src/app/team-management/member-detail/member-detail.component.ts index e407144f63..63b79efbf7 100644 --- a/frontend/src/app/team-management/member-detail/member-detail.component.ts +++ b/frontend/src/app/team-management/member-detail/member-detail.component.ts @@ -8,7 +8,6 @@ import { UserTeam } from '../../shared/types/model/UserTeam'; import { TranslateService } from '@ngx-translate/core'; import { MatTable } from '@angular/material/table'; import { TeamService } from '../../services/team.service'; -import { CancelDialogComponent } from '../../shared/dialog/cancel-dialog/cancel-dialog.component'; import { DialogService } from '../../services/dialog.service'; @Component({ @@ -79,12 +78,12 @@ export class MemberDetailComponent implements OnInit, OnDestroy { } removeUserFromTeam(userTeam: UserTeam, user: User) { + const i18nData = { + user: getFullNameFromUser(user), + team: userTeam.team.name, + }; this.dialogService - .open(CancelDialogComponent, { - data: { - dialogTitle: getFullNameFromUser(user) + ` wirklich aus Team ${userTeam.team.name} entfernen?`, - }, - }) + .openConfirmDialog('CONFIRMATION.DELETE.USER_FROM_TEAM', i18nData) .afterClosed() .pipe( filter((confirm) => confirm), diff --git a/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.spec.ts b/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.spec.ts index b8f9194361..aec9651433 100644 --- a/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.spec.ts +++ b/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.spec.ts @@ -95,7 +95,7 @@ describe('MemberListTableComponent', () => { teamServiceMock.removeUserFromTeam.mockReturnValue(of(null)); userServiceMock.reloadUsers.mockReturnValue(of()); userServiceMock.reloadCurrentUser.mockReturnValue(of()); - dialogService.open.mockReturnValue({ + dialogService.openConfirmDialog.mockReturnValue({ afterClosed: () => of(true), }); @@ -116,7 +116,7 @@ describe('MemberListTableComponent', () => { teamServiceMock.removeUserFromTeam.mockReturnValue(of(null)); userServiceMock.reloadUsers.mockReturnValue(of()); userServiceMock.reloadCurrentUser.mockReturnValue(of()); - dialogService.open.mockReturnValue({ + dialogService.openConfirmDialog.mockReturnValue({ afterClosed: () => of(false), }); diff --git a/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.ts b/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.ts index a9282e329f..1c1f587343 100644 --- a/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.ts +++ b/frontend/src/app/team-management/member-list/member-list-table/member-list-table.component.ts @@ -8,7 +8,6 @@ import { UserService } from '../../../services/user.service'; import { getRouteToUserDetails } from '../../../shared/routeUtils'; import { BehaviorSubject, filter, mergeMap, Subject, takeUntil } from 'rxjs'; import { UserTeam } from '../../../shared/types/model/UserTeam'; -import { CancelDialogComponent } from '../../../shared/dialog/cancel-dialog/cancel-dialog.component'; import { DialogService } from '../../../services/dialog.service'; @Component({ @@ -57,13 +56,12 @@ export class MemberListTableComponent implements OnInit, OnDestroy { removeMemberFromTeam(entry: UserTableEntry, event: MouseEvent) { event.stopPropagation(); event.preventDefault(); - + const i18nData = { + user: `${entry.firstname} ${entry.lastname}`, + team: this.selectedTeam$.value?.name, + }; this.dialogService - .open(CancelDialogComponent, { - data: { - dialogTitle: `${entry.firstname} ${entry.lastname} wirklich aus Team ${this.selectedTeam$.value?.name} entfernen?`, - }, - }) + .openConfirmDialog('CONFIRMATION.DELETE.USER_FROM_TEAM', i18nData) .afterClosed() .pipe( filter((confirm) => confirm), diff --git a/frontend/src/app/team-management/member-list/member-list.component.spec.ts b/frontend/src/app/team-management/member-list/member-list.component.spec.ts index 052ad6c0bf..b54e9ee180 100644 --- a/frontend/src/app/team-management/member-list/member-list.component.spec.ts +++ b/frontend/src/app/team-management/member-list/member-list.component.spec.ts @@ -18,6 +18,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { MemberListTableComponent } from './member-list-table/member-list-table.component'; import { MemberListMobileComponent } from './member-list-mobile/member-list-mobile.component'; import { DialogService } from '../../services/dialog.service'; +import { provideHttpClient } from '@angular/common/http'; const userServiceMock = { getUsers: jest.fn(), @@ -184,7 +185,7 @@ describe('MemberListComponent', () => { it('deleteTeam should trigger teamService.deleteTeam and navigate', fakeAsync(() => { routerMock.navigateByUrl.mockReturnValue(of(null)); teamServiceMock.deleteTeam.mockReturnValue(of(null)); - dialogService.open.mockReturnValue({ + dialogService.openConfirmDialog.mockReturnValue({ afterClosed: () => of(true), }); @@ -204,7 +205,7 @@ describe('MemberListComponent', () => { it('deleteTeam should not trigger teamService.deleteTeam if dialog is canceled', fakeAsync(() => { routerMock.navigateByUrl.mockReturnValue(of(null)); teamServiceMock.deleteTeam.mockReturnValue(of(null)); - dialogService.open.mockReturnValue({ + dialogService.openConfirmDialog.mockReturnValue({ afterClosed: () => of(false), }); diff --git a/frontend/src/app/team-management/member-list/member-list.component.ts b/frontend/src/app/team-management/member-list/member-list.component.ts index 264af1dce5..1ae5ba4865 100644 --- a/frontend/src/app/team-management/member-list/member-list.component.ts +++ b/frontend/src/app/team-management/member-list/member-list.component.ts @@ -84,13 +84,12 @@ export class MemberListComponent implements OnInit, OnDestroy, AfterViewInit { } deleteTeam(selectedTeam: Team) { + const data = { + team: selectedTeam.name, + }; + this.dialogService - .open(CancelDialogComponent, { - data: { - dialogTitle: selectedTeam.name + ' wirklich löschen?', - dialogText: 'Soll das Team und dessen OKRs wirklich gelöscht werden?', - }, - }) + .openConfirmDialog('CONFIRMATION.DELETE.TEAM', data) .afterClosed() .pipe( filter((confirm) => confirm), diff --git a/frontend/src/assets/i18n/de.json b/frontend/src/assets/i18n/de.json index fb5e054302..5e2086cf7e 100644 --- a/frontend/src/assets/i18n/de.json +++ b/frontend/src/assets/i18n/de.json @@ -84,8 +84,8 @@ "TEXT": "Möchtest du die Action wirklich löschen?" }, "TEAM":{ - "TITLE": "Löschen bestätigen", - "TEXT": "Möchtest du dieses Team wirklich löschen? Zugehörige Objectives werden dadurch in allen Quartalen ebenfalls gelöscht!" + "TITLE": "Team löschen", + "TEXT": "Möchtest du das Team '{{team}}' wirklich löschen? Zugehörige Objectives werden dadurch in allen Quartalen ebenfalls gelöscht!" }, "OBJECTIVE":{ "TITLE": "Objective löschen", @@ -94,6 +94,10 @@ "KEYRESULT":{ "TITLE": "Key Result löschen", "TEXT": "Möchtest du dieses Key Result wirklich löschen? Zugehörige Check-ins werden dadurch ebenfalls gelöscht!" + }, + "USER_FROM_TEAM":{ + "TITLE": "Mitglied entfernen", + "TEXT": "Möchtest du {{user}} wirklich aus dem Team '{{team}}' entfernen?" } } }, diff --git a/frontend/src/style/custom_angular.components.scss b/frontend/src/style/custom_angular.components.scss index 3e65e2d3b5..46e8b82be5 100644 --- a/frontend/src/style/custom_angular.components.scss +++ b/frontend/src/style/custom_angular.components.scss @@ -48,15 +48,6 @@ display: none !important; } -.mat-mdc-dialog-surface { - padding: 1rem 0 1rem 0; -} - -mat-dialog-content, -mat-dialog-actions { - padding: 0 1.62rem 0 1.62rem !important; -} - //Offset for top bar .cdk-overlay-backdrop.cdk-overlay-dark-backdrop.cdk-overlay-backdrop-showing { margin-top: $top-bar-height; diff --git a/frontend/src/style/styles.scss b/frontend/src/style/styles.scss index bfd8c3f7df..fd1cd5ccac 100644 --- a/frontend/src/style/styles.scss +++ b/frontend/src/style/styles.scss @@ -47,15 +47,6 @@ body.okr { p { margin: 0; - font-size: 14px; - } - - span { - font-size: 14px; - } - - .quarter-filter-text span { - font-size: 16px; } a { @@ -348,7 +339,52 @@ table.okr-table { } .okr-dialog-panel { + margin-top: $top-bar-height; + max-height: calc(100vh - $top-bar-height); @extend .col-12; +} +.okr-dialog-panel-default { + @extend .okr-dialog-panel; + @extend .col-sm-8; @extend .col-md-6; + @extend .col-lg-5; + @extend .col-xxl-4; + @include media-breakpoint-down(sm) { + height: 100%; + } +} + +.okr-dialog-panel-small { + @extend .okr-dialog-panel; + @extend .col-sm-8; + @extend .col-md-6; + @extend .col-lg-5; + @extend .col-xl-4; + @extend .col-xxl-3; +} + +.okr-form-container { + @extend .container-fluid; +} + +.okr-form-row { + @extend .row; +} + +.okr-form-col { + @extend .col-12; +} + +.okr-form-label { + color: black; + @extend .py-1; +} + +// Is used to style the input fields in the OKR form globally +.okr-form-input { + @extend .okr-form-col; +} + +.okr-form-label-input-container { } From 34f88f59ac0a0bafe0c5fb227b24e68d7bb663f0 Mon Sep 17 00:00:00 2001 From: nevio18324 <141240169+nevio18324@users.noreply.github.com> Date: Wed, 6 Nov 2024 13:08:40 +0100 Subject: [PATCH 18/28] Bug/1013 routing to overview (#1084) * Add permanent teamverwaltung button and make logo route to / * Make router links leading to homepage preserve query params * Change tag around logo from span to a * Add e2e tests that test if route is preserved --------- Co-authored-by: Jannik Pulfer Co-authored-by: GitHub Actions --- .../application-top-bar.component.html | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/components/application-top-bar/application-top-bar.component.html b/frontend/src/app/components/application-top-bar/application-top-bar.component.html index 74b1855ef9..3b66f02ff5 100644 --- a/frontend/src/app/components/application-top-bar/application-top-bar.component.html +++ b/frontend/src/app/components/application-top-bar/application-top-bar.component.html @@ -1,8 +1,15 @@
- - okr-logo - + + okr-logo +
-
+
{{ objective.title }} [keyResult]="keyResult" [attr.data-testId]="'keyresult'" > -
+
+
diff --git a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.html b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.html index 3c796f384f..f66dfb6ea5 100644 --- a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.html +++ b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.html @@ -27,7 +27,7 @@

Letzter Wert

-
{{ checkIn.value }} {{ generateUnitLabel() }}
+
{{ checkIn.value }}{{ generateUnitLabel() }}
diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index 1ed7295b52..783ed85b71 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -25,6 +25,7 @@ import { SpinnerComponent } from './custom/spinner/spinner.component'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { DialogTemplateCoreComponent } from './custom/dialog-template-core/dialog-template-core.component'; import { MatDividerModule } from '@angular/material/divider'; +import { UnitLabelTransformationPipe } from './pipes/unit-label-transformation/unit-label-transformation.pipe'; @NgModule({ declarations: [ From 65b96108af1641729e3279ba358697244ba9c042 Mon Sep 17 00:00:00 2001 From: Manuel <109959820+ManuelMoeri@users.noreply.github.com> Date: Fri, 8 Nov 2024 14:52:59 +0100 Subject: [PATCH 21/28] Feature/977 HTML structure (#1040) * Implement html structure and fix tests * Shorten logic in component * Remove unwanted styling that broke every dialog * Add styling to headings and fix obvious mistakes * Fix font size in banner and alignment of stretch star * Fix e2e test * Remove files that do not belong to my PR --- .../components/action-plan/action-plan.component.html | 2 +- .../components/confidence/confidence.component.html | 2 +- .../keyresult-detail/keyresult-detail.component.html | 2 +- .../app/components/objective/objective.component.html | 8 ++++---- frontend/src/style/styles.scss | 10 ++++++++++ 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/frontend/src/app/components/action-plan/action-plan.component.html b/frontend/src/app/components/action-plan/action-plan.component.html index 0dc3ac9c45..68388cea32 100644 --- a/frontend/src/app/components/action-plan/action-plan.component.html +++ b/frontend/src/app/components/action-plan/action-plan.component.html @@ -42,7 +42,7 @@
-
+
-
+
{{ objective.title }} [keyResult]="keyResult" [attr.data-testId]="'keyresult'" > -
+