From 94635ebae68e1efc437690b30eca16e0fe3d5aa2 Mon Sep 17 00:00:00 2001 From: toni Date: Sat, 3 Jan 2026 02:31:43 +0100 Subject: [PATCH] zoneless + fix signal form refresh --- packages/api/src/services/membersService.ts | 12 +-- packages/frontend/angular.json | 2 - packages/frontend/package.json | 3 +- packages/frontend/src/app/app.config.ts | 11 ++- packages/frontend/src/app/app.ts | 9 ++- .../delete-member-dialog.component.html | 6 +- .../delete-member-dialog.component.ts | 18 +++-- .../edit-member-dialog.component.html | 6 +- .../edit-member-dialog.component.ts | 15 +++- .../frontend/src/app/components/home/home.ts | 3 +- .../src/app/components/login/login.ts | 27 +++---- .../components/missing-page/missing-page.ts | 3 +- .../new-member/new-member.component.html | 6 +- .../new-member/new-member.component.ts | 25 ++++--- .../frontend/src/app/components/test/test.ts | 74 +++++++++++-------- .../components/view-members/view-members.ts | 7 +- packages/frontend/src/index.html | 1 + pnpm-lock.yaml | 40 +++++----- 18 files changed, 156 insertions(+), 112 deletions(-) diff --git a/packages/api/src/services/membersService.ts b/packages/api/src/services/membersService.ts index fe0b5d6..3957736 100644 --- a/packages/api/src/services/membersService.ts +++ b/packages/api/src/services/membersService.ts @@ -43,12 +43,14 @@ export class MembersService { createArgs: MemberCreateArgs, request: express.Request, ): Promise { - // const x: MemberCreateArgs = { - // ...createArgs, - // geburtsdatum: createArgs.geburtsdatum ?? null, - // }; + const x = { + ...createArgs, + geburtsdatum: createArgs.geburtsdatum + ? createArgs.geburtsdatum + : null, + }; const newMember = await this.database.doRequest( - async prisma => await prisma.member.create({ data: createArgs }), + async prisma => await prisma.member.create({ data: x }), request, ); return mapDbMemberToMember(newMember); diff --git a/packages/frontend/angular.json b/packages/frontend/angular.json index c9d46c4..70a935a 100644 --- a/packages/frontend/angular.json +++ b/packages/frontend/angular.json @@ -21,7 +21,6 @@ "builder": "@angular/build:application", "options": { "browser": "src/main.ts", - "polyfills": ["zone.js"], "tsConfig": "tsconfig.app.json", "inlineStyleLanguage": "scss", "assets": [ @@ -75,7 +74,6 @@ "test": { "builder": "@angular/build:karma", "options": { - "polyfills": ["zone.js", "zone.js/testing"], "tsConfig": "tsconfig.spec.json", "inlineStyleLanguage": "scss", "assets": [ diff --git a/packages/frontend/package.json b/packages/frontend/package.json index fbcab0b..4d7865a 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -42,8 +42,7 @@ "keycloak-angular": "^20.0.0", "keycloak-js": "^26.2.1", "rxjs": "~7.8.2", - "tslib": "^2.8.1", - "zone.js": "~0.15.1" + "tslib": "^2.8.1" }, "devDependencies": { "@angular/build": "^21.0.4", diff --git a/packages/frontend/src/app/app.config.ts b/packages/frontend/src/app/app.config.ts index 9b1e34f..5790f67 100644 --- a/packages/frontend/src/app/app.config.ts +++ b/packages/frontend/src/app/app.config.ts @@ -4,7 +4,8 @@ import { LOCALE_ID, provideAppInitializer, provideBrowserGlobalErrorListeners, - provideZoneChangeDetection, + provideCheckNoChangesConfig, + provideZonelessChangeDetection, } from '@angular/core'; import { PreloadAllModules, @@ -48,7 +49,7 @@ export const appConfig: ApplicationConfig = { withComponentInputBinding(), ), provideBrowserGlobalErrorListeners(), - provideZoneChangeDetection({ eventCoalescing: true }), + provideZonelessChangeDetection(), provideKeycloak({ config: keycloakConfig, initOptions: { @@ -90,3 +91,9 @@ export const appConfig: ApplicationConfig = { }), ], }; + +if (isDevMode()) { + appConfig.providers.push( + provideCheckNoChangesConfig({ exhaustive: true, interval: 100 }), + ); +} diff --git a/packages/frontend/src/app/app.ts b/packages/frontend/src/app/app.ts index 2dd53a3..b29a81a 100644 --- a/packages/frontend/src/app/app.ts +++ b/packages/frontend/src/app/app.ts @@ -1,4 +1,10 @@ -import { Component, effect, inject, signal } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + effect, + inject, + signal, +} from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { RouterModule, RouterOutlet } from '@angular/router'; import { Authentication } from './services/authentication'; @@ -9,6 +15,7 @@ import { keycloakConfig } from './util/keycloak-config'; imports: [RouterOutlet, MatButtonModule, RouterModule], templateUrl: './app.html', styleUrl: './app.scss', + changeDetection: ChangeDetectionStrategy.OnPush, }) export class App { protected readonly title = signal('frontend'); diff --git a/packages/frontend/src/app/components/delete-member-dialog/delete-member-dialog.component.html b/packages/frontend/src/app/components/delete-member-dialog/delete-member-dialog.component.html index 62dee46..ca35790 100644 --- a/packages/frontend/src/app/components/delete-member-dialog/delete-member-dialog.component.html +++ b/packages/frontend/src/app/components/delete-member-dialog/delete-member-dialog.component.html @@ -1,4 +1,4 @@ -
+

Name: {{ member.vorname }} {{ member.nachname }}

Passnummer: {{ member.passnummer }}

Geburtsdatum: {{ member.geburtsdatum | datePipe }}

@@ -11,7 +11,5 @@ [for]="picker"> - +
diff --git a/packages/frontend/src/app/components/delete-member-dialog/delete-member-dialog.component.ts b/packages/frontend/src/app/components/delete-member-dialog/delete-member-dialog.component.ts index 8a91551..4e8db82 100644 --- a/packages/frontend/src/app/components/delete-member-dialog/delete-member-dialog.component.ts +++ b/packages/frontend/src/app/components/delete-member-dialog/delete-member-dialog.component.ts @@ -1,4 +1,9 @@ -import { Component, inject, signal } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + inject, + signal, +} from '@angular/core'; import { Field, form } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; @@ -32,6 +37,7 @@ import { EditMemberDialogComponent } from '../edit-member-dialog/edit-member-dia ], templateUrl: './delete-member-dialog.component.html', styleUrl: './delete-member-dialog.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, }) export class DeleteMemberDialogComponent { private readonly data = inject<{ member: api.MemberDto }>(MAT_DIALOG_DATA); @@ -46,13 +52,13 @@ export class DeleteMemberDialogComponent { protected readonly form = form(this.deletionModel); protected readonly member = this.data.member; - protected async submit() { + protected submit() { const date = this.deletionModel().kuendigungzum; - await api.scheduleDeletion( + api.scheduleDeletion( this.member.id, date ? dateToLocal(date).toISOString() : '', - ); - - this.dialogRef.close(); + ).then(() => { + this.dialogRef.close(); + }); } } diff --git a/packages/frontend/src/app/components/edit-member-dialog/edit-member-dialog.component.html b/packages/frontend/src/app/components/edit-member-dialog/edit-member-dialog.component.html index 5c2a035..ccc3b48 100644 --- a/packages/frontend/src/app/components/edit-member-dialog/edit-member-dialog.component.html +++ b/packages/frontend/src/app/components/edit-member-dialog/edit-member-dialog.component.html @@ -1,4 +1,4 @@ -
+ Vorname @@ -35,7 +35,5 @@ Nein - +
diff --git a/packages/frontend/src/app/components/edit-member-dialog/edit-member-dialog.component.ts b/packages/frontend/src/app/components/edit-member-dialog/edit-member-dialog.component.ts index 9455d96..21c9c77 100644 --- a/packages/frontend/src/app/components/edit-member-dialog/edit-member-dialog.component.ts +++ b/packages/frontend/src/app/components/edit-member-dialog/edit-member-dialog.component.ts @@ -1,4 +1,9 @@ -import { Component, inject, signal } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + inject, + signal, +} from '@angular/core'; import { Field, form } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; @@ -26,6 +31,7 @@ import { MemberDtoHelper, MemberEditForm } from '../../util/member.js'; ], templateUrl: './edit-member-dialog.component.html', styleUrl: './edit-member-dialog.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, }) export class EditMemberDialogComponent { private readonly data = inject<{ member: api.MemberDto }>(MAT_DIALOG_DATA); @@ -39,11 +45,12 @@ export class EditMemberDialogComponent { ); protected readonly form = form(this.memberModel); - protected async submit() { + protected submit() { const member: api.MemberDto = this.memberDtoHelper.memberFromSignal( this.memberModel(), ); - await api.updateMember(member); - this.dialogRef.close(); + api.updateMember(member).then(() => { + this.dialogRef.close(); + }); } } diff --git a/packages/frontend/src/app/components/home/home.ts b/packages/frontend/src/app/components/home/home.ts index 9e482b0..3b55c45 100644 --- a/packages/frontend/src/app/components/home/home.ts +++ b/packages/frontend/src/app/components/home/home.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatListModule } from '@angular/material/list'; import { RouterModule } from '@angular/router'; @@ -15,6 +15,7 @@ import { Claim } from '../../generated-api/api'; ], templateUrl: './home.html', styleUrl: './home.scss', + changeDetection: ChangeDetectionStrategy.OnPush, }) export class Home { protected Claim = Claim; diff --git a/packages/frontend/src/app/components/login/login.ts b/packages/frontend/src/app/components/login/login.ts index 82e9dfb..3e3f62c 100644 --- a/packages/frontend/src/app/components/login/login.ts +++ b/packages/frontend/src/app/components/login/login.ts @@ -1,22 +1,23 @@ -import { Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { Router } from '@angular/router'; import { Authentication } from '../../services/authentication'; @Component({ - selector: 'app-login', - imports: [], - templateUrl: './login.html', - styleUrl: './login.scss', + selector: 'app-login', + imports: [], + templateUrl: './login.html', + styleUrl: './login.scss', + changeDetection: ChangeDetectionStrategy.OnPush, }) export class Login { - private readonly authentication = inject(Authentication); - private readonly router = inject(Router); + private readonly authentication = inject(Authentication); + private readonly router = inject(Router); - public constructor() { - if(this.authentication.loggedIn()){ - this.router.navigate(['/home']); - }else{ - this.authentication.login(); + public constructor() { + if (this.authentication.loggedIn()) { + this.router.navigate(['/home']); + } else { + this.authentication.login(); + } } - } } diff --git a/packages/frontend/src/app/components/missing-page/missing-page.ts b/packages/frontend/src/app/components/missing-page/missing-page.ts index 27ab21d..f1c2ddd 100644 --- a/packages/frontend/src/app/components/missing-page/missing-page.ts +++ b/packages/frontend/src/app/components/missing-page/missing-page.ts @@ -1,4 +1,4 @@ -import { Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { RouterModule } from '@angular/router'; import { Authentication } from '../../services/authentication'; @@ -8,6 +8,7 @@ import { Authentication } from '../../services/authentication'; imports: [MatButtonModule, RouterModule], templateUrl: './missing-page.html', styleUrl: './missing-page.scss', + changeDetection: ChangeDetectionStrategy.OnPush, }) export class MissingPage { protected readonly auth = inject(Authentication); diff --git a/packages/frontend/src/app/components/new-member/new-member.component.html b/packages/frontend/src/app/components/new-member/new-member.component.html index 205c0c1..9ed86f1 100644 --- a/packages/frontend/src/app/components/new-member/new-member.component.html +++ b/packages/frontend/src/app/components/new-member/new-member.component.html @@ -1,5 +1,5 @@

Neues Mitglied anlegen

-
+ Vorname @@ -37,7 +37,5 @@ Kontakt - +
diff --git a/packages/frontend/src/app/components/new-member/new-member.component.ts b/packages/frontend/src/app/components/new-member/new-member.component.ts index 395049e..36491ef 100644 --- a/packages/frontend/src/app/components/new-member/new-member.component.ts +++ b/packages/frontend/src/app/components/new-member/new-member.component.ts @@ -1,4 +1,9 @@ -import { Component, inject, signal } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + inject, + signal, +} from '@angular/core'; import { Field, form } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; @@ -23,6 +28,7 @@ import { MemberCreateForm, MemberDtoHelper } from '../../util/member.js'; ], templateUrl: './new-member.component.html', styleUrl: './new-member.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, }) export class NewMemberComponent { private readonly memberDtoHelper = inject(MemberDtoHelper); @@ -35,7 +41,7 @@ export class NewMemberComponent { ); protected readonly memberForm = form(this.memberModel); - protected async onSubmit(): Promise { + protected onSubmit() { if (!this.memberForm().valid()) { return; } @@ -44,12 +50,13 @@ export class NewMemberComponent { this.memberModel(), ); - try { - await api.createMember(newMember); - console.log('Successfully added Member'); - this.dialogRef.close(); - } catch (e) { - console.error('Error adding member', e); - } + api.createMember(newMember) + .then(() => { + console.log('Successfully added Member'); + this.dialogRef.close(); + }) + .catch(e => { + console.error('Error adding member', e); + }); } } diff --git a/packages/frontend/src/app/components/test/test.ts b/packages/frontend/src/app/components/test/test.ts index 1648abc..f4205f7 100644 --- a/packages/frontend/src/app/components/test/test.ts +++ b/packages/frontend/src/app/components/test/test.ts @@ -1,42 +1,52 @@ import { JsonPipe } from '@angular/common'; -import { Component, effect, inject, signal } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + effect, + inject, + signal, +} from '@angular/core'; import * as api from '../../generated-api/api'; import { Authentication } from '../../services/authentication'; @Component({ - selector: 'app-test', - imports: [JsonPipe], - templateUrl: './test.html', - styleUrl: './test.scss', + selector: 'app-test', + imports: [JsonPipe], + templateUrl: './test.html', + styleUrl: './test.scss', + changeDetection: ChangeDetectionStrategy.OnPush, }) export class Test { - protected auth = inject(Authentication); + protected auth = inject(Authentication); - protected apiStatus = signal("Waiting"); - protected authTest = signal("Waiting"); - - public constructor(){ - effect(()=>{ - const loggedIn=this.auth.loggedIn(); - if(!loggedIn){ - this.apiStatus.set("N/A - not logged in"); - this.authTest.set("N/A - not logged in"); - return; + protected apiStatus = signal('Waiting'); + protected authTest = signal('Waiting'); + + public constructor() { + effect(() => { + const loggedIn = this.auth.loggedIn(); + if (!loggedIn) { + this.apiStatus.set('N/A - not logged in'); + this.authTest.set('N/A - not logged in'); + return; + } + + this.apiStatus.set('Waiting for API'); + this.authTest.set('Waiting for API'); + api.getOk() + .then(status => { + this.apiStatus.set('Ok'); + }) + .catch(e => { + this.apiStatus.set('Error'); + }); + api.getAuth() + .then(response => { + this.authTest.set('Ok'); + }) + .catch(e => { + this.authTest.set(e); + }); + }); } - - this.apiStatus.set("Waiting for API"); - this.authTest.set("Waiting for API"); - api.getOk().then((status) => { - this.apiStatus.set("Ok"); - }).catch((e) => { - this.apiStatus.set("Error"); - }); - api.getAuth().then((response) => { - this.authTest.set("Ok"); - }).catch((e) => { - this.authTest.set(e); - }); - }) - } - } diff --git a/packages/frontend/src/app/components/view-members/view-members.ts b/packages/frontend/src/app/components/view-members/view-members.ts index 5fc140e..7dd93c5 100644 --- a/packages/frontend/src/app/components/view-members/view-members.ts +++ b/packages/frontend/src/app/components/view-members/view-members.ts @@ -1,5 +1,6 @@ import { AfterViewInit, + ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, @@ -56,10 +57,11 @@ enum MemberStatusFilter { ], templateUrl: './view-members.html', styleUrl: './view-members.scss', + changeDetection: ChangeDetectionStrategy.OnPush, }) export class ViewMembers implements AfterViewInit { private readonly changeDetectorRef = inject(ChangeDetectorRef); - + protected readonly MemberStatusFilter = MemberStatusFilter; private readonly filterModel = signal({ filterString: '', @@ -73,7 +75,6 @@ export class ViewMembers implements AfterViewInit { () => this.filterForm.status().value() === MemberStatusFilter.ALL, ); - protected readonly dataSource = new MatTableDataSource(); private readonly datePipe = new DatePipePipe(); @@ -206,6 +207,6 @@ export class ViewMembers implements AfterViewInit { private async updateData(): Promise { const members = await api.getMembers(); this.dataSource.data = members; - this.changeDetectorRef.detectChanges(); + this.changeDetectorRef.markForCheck(); } } diff --git a/packages/frontend/src/index.html b/packages/frontend/src/index.html index 69362a4..e8aa183 100644 --- a/packages/frontend/src/index.html +++ b/packages/frontend/src/index.html @@ -6,6 +6,7 @@ 1.TC Chemnitz Mitgliederdatenbank +