feat: migrate to Angular 20 and update all dependencies

- Update Angular core packages from v19 to v20.1.6
- Update Angular Material/CDK to v20.1.5
- Update NgRx packages to v20.0.0
- Update ngx-translate to v17.0.0 with new provider pattern
- Update ngx-markdown to v20.0.0
- Update ngx-formly to v7.0.0
- Update angular-material-css-vars to v9.1.1
- Update Angular ESLint packages to v20.1.1
- Update Angular builders to v20.0.0
- Fix NgRx entity state TypeScript errors (removed explicit ids property)
- Fix TranslateHttpLoader configuration for v17 (use TRANSLATE_HTTP_LOADER_CONFIG)
- Update provideExperimentalZonelessChangeDetection to provideZonelessChangeDetection
- Remove unused AsyncPipe import from MetricComponent

BREAKING CHANGE: Requires Node.js v20.19+ or v22.12+
This commit is contained in:
Johannes Millan 2025-08-13 18:41:24 +02:00
parent b91edd6ada
commit 364dd8af95
6 changed files with 180 additions and 2801 deletions

2922
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -140,13 +140,13 @@
"node-fetch": "^2.7.0"
},
"devDependencies": {
"@angular-builders/custom-webpack": "^19.0.1",
"@angular-builders/custom-webpack": "^20.0.0",
"@angular-devkit/build-angular": "^20.1.5",
"@angular-eslint/builder": "^19.3.0",
"@angular-eslint/eslint-plugin": "^19.3.0",
"@angular-eslint/eslint-plugin-template": "^19.3.0",
"@angular-eslint/builder": "^20.1.1",
"@angular-eslint/eslint-plugin": "^20.1.1",
"@angular-eslint/eslint-plugin-template": "^20.1.1",
"@angular-eslint/schematics": "^20.1.1",
"@angular-eslint/template-parser": "^19.3.0",
"@angular-eslint/template-parser": "^20.1.1",
"@angular/animations": "^20.1.6",
"@angular/cdk": "^20.1.5",
"@angular/cli": "^20.1.5",
@ -180,10 +180,10 @@
"@ngrx/schematics": "^20.0.0",
"@ngrx/store": "20.0.0",
"@ngrx/store-devtools": "^20.0.0",
"@ngx-formly/core": "6.3.12",
"@ngx-formly/material": "6.3.12",
"@ngx-translate/core": "^16.0.3",
"@ngx-translate/http-loader": "^16.0.1",
"@ngx-formly/core": "7.0.0",
"@ngx-formly/material": "7.0.0",
"@ngx-translate/core": "^17.0.0",
"@ngx-translate/http-loader": "^17.0.0",
"@playwright/test": "^1.54.1",
"@schematics/angular": "^20.1.4",
"@types/electron-localshortcut": "^3.1.3",
@ -197,7 +197,7 @@
"@typescript-eslint/parser": "7.18.0",
"@typescript-eslint/types": "^8.17.0",
"@typescript-eslint/utils": "^8.35.1",
"angular-material-css-vars": "^8.0.0",
"angular-material-css-vars": "^9.1.1",
"angular-mentions": "^1.5.0",
"canvas-confetti": "^1.9.3",
"chai": "^5.1.2",
@ -236,7 +236,7 @@
"nanoid": "^5.1.5",
"new-github-issue-url": "^1.1.0",
"ng2-charts": "^8.0.0",
"ngx-markdown": "^19.0.0",
"ngx-markdown": "^20.0.0",
"playwright": "^1.54.1",
"prettier": "^3.5.1",
"pretty-quick": "^4.1.1",

View file

@ -7,7 +7,7 @@ import { T } from '../../t.const';
import { ProjectMetricsService } from './project-metrics.service';
import { WorkContextService } from '../work-context/work-context.service';
import { LazyChartComponent } from './lazy-chart/lazy-chart.component';
import { AsyncPipe, DecimalPipe } from '@angular/common';
import { DecimalPipe } from '@angular/common';
import { MsToStringPipe } from '../../ui/duration/ms-to-string.pipe';
import { TranslatePipe } from '@ngx-translate/core';
@ -17,7 +17,7 @@ import { TranslatePipe } from '@ngx-translate/core';
styleUrls: ['./metric.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
animations: [fadeAnimation],
imports: [LazyChartComponent, AsyncPipe, DecimalPipe, MsToStringPipe, TranslatePipe],
imports: [LazyChartComponent, DecimalPipe, MsToStringPipe, TranslatePipe],
})
export class MetricComponent {
workContextService = inject(WorkContextService);

View file

@ -22,7 +22,6 @@ import { TaskSharedActions } from '../../../root-store/meta/task-shared.actions'
export const adapter: EntityAdapter<Note> = createEntityAdapter<Note>();
export const initialNoteState: NoteState = adapter.getInitialState({
ids: [],
todayOrder: [],
});

View file

@ -58,9 +58,6 @@ export const TASK_FEATURE_NAME = 'tasks';
// REDUCER
// -------
export const initialTaskState: TaskState = taskAdapter.getInitialState({
// overwrite entity model to avoid problems with typing
ids: [],
// TODO maybe at least move those properties to an ui property
currentTaskId: null,
selectedTaskId: null,

View file

@ -16,11 +16,7 @@ import { androidInterface } from './app/features/android/android-interface';
import { App as CapacitorApp } from '@capacitor/app';
import { GlobalErrorHandler } from './app/core/error-handler/global-error-handler.class';
import { bootstrapApplication, BrowserModule } from '@angular/platform-browser';
import {
HttpClient,
provideHttpClient,
withInterceptorsFromDi,
} from '@angular/common/http';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { MarkdownModule, MARKED_OPTIONS, provideMarkdown } from 'ngx-markdown';
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
import { FeatureStoresModule } from './app/root-store/feature-stores.module';
@ -46,8 +42,8 @@ import {
plannerSharedMetaReducer,
projectSharedMetaReducer,
tagSharedMetaReducer,
taskSharedCrudMetaReducer,
taskBatchUpdateMetaReducer,
taskSharedCrudMetaReducer,
taskSharedLifecycleMetaReducer,
taskSharedSchedulingMetaReducer,
} from './app/root-store/meta/task-shared-meta-reducers';
@ -55,10 +51,13 @@ import { EffectsModule } from '@ngrx/effects';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { ReactiveFormsModule } from '@angular/forms';
import { ServiceWorkerModule } from '@angular/service-worker';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import {
TranslateHttpLoader,
TRANSLATE_HTTP_LOADER_CONFIG,
} from '@ngx-translate/http-loader';
import { CdkDropListGroup } from '@angular/cdk/drag-drop';
import { AppComponent } from './app/app.component';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { ShortTimeHtmlPipe } from './app/ui/pipes/short-time-html.pipe';
import { ShortTimePipe } from './app/ui/pipes/short-time.pipe';
import { BackgroundTask } from '@capawesome/capacitor-background-task';
@ -73,11 +72,16 @@ if (environment.production || environment.stage) {
// Window.ea declaration is in src/app/core/window-ea.d.ts
const createTranslateLoader = (http: HttpClient): TranslateHttpLoader =>
new TranslateHttpLoader(http, './assets/i18n/', '.json');
bootstrapApplication(AppComponent, {
providers: [
// Provide configuration for TranslateHttpLoader
{
provide: TRANSLATE_HTTP_LOADER_CONFIG,
useValue: {
prefix: './assets/i18n/',
suffix: '.json',
},
},
importProvidersFrom(
FeatureStoresModule,
MatNativeDateModule,
@ -144,8 +148,7 @@ bootstrapApplication(AppComponent, {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: createTranslateLoader,
deps: [HttpClient],
useClass: TranslateHttpLoader,
},
}),
CdkDropListGroup,