Upgraded to Angular 20

This commit is contained in:
Joseph Milazzo 2025-07-12 13:36:06 -05:00
parent 3c28291cdb
commit a3d999b7b9
13 changed files with 3241 additions and 1269 deletions

View File

@ -123,5 +123,31 @@
}
}
}
},
"schematics": {
"@schematics/angular:component": {
"type": "component"
},
"@schematics/angular:directive": {
"type": "directive"
},
"@schematics/angular:service": {
"type": "service"
},
"@schematics/angular:guard": {
"typeSeparator": "."
},
"@schematics/angular:interceptor": {
"typeSeparator": "."
},
"@schematics/angular:module": {
"typeSeparator": "."
},
"@schematics/angular:pipe": {
"typeSeparator": "."
},
"@schematics/angular:resolver": {
"typeSeparator": "."
}
}
}

4341
UI/Web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -16,70 +16,70 @@
},
"private": true,
"dependencies": {
"@angular-slider/ngx-slider": "^19.0.0",
"@angular/animations": "^19.2.5",
"@angular/cdk": "^19.2.8",
"@angular/common": "^19.2.5",
"@angular/compiler": "^19.2.5",
"@angular/core": "^19.2.5",
"@angular/forms": "^19.2.5",
"@angular/localize": "^19.2.5",
"@angular/platform-browser": "^19.2.5",
"@angular/platform-browser-dynamic": "^19.2.5",
"@angular/router": "^19.2.5",
"@angular-slider/ngx-slider": "^20.0.0",
"@angular/animations": "^20.1.0",
"@angular/cdk": "^20.1.0",
"@angular/common": "^20.1.0",
"@angular/compiler": "^20.1.0",
"@angular/core": "^20.1.0",
"@angular/forms": "^20.1.0",
"@angular/localize": "^20.1.0",
"@angular/platform-browser": "^20.1.0",
"@angular/platform-browser-dynamic": "^20.1.0",
"@angular/router": "^20.1.0",
"@fortawesome/fontawesome-free": "^6.7.2",
"@iharbeck/ngx-virtual-scroller": "^19.0.1",
"@iplab/ngx-file-upload": "^19.0.3",
"@iplab/ngx-file-upload": "^20.0.0",
"@jsverse/transloco": "^7.6.1",
"@jsverse/transloco-locale": "^7.0.1",
"@jsverse/transloco-persist-lang": "^7.0.2",
"@jsverse/transloco-persist-translations": "^7.0.1",
"@jsverse/transloco-preload-langs": "^7.0.1",
"@microsoft/signalr": "^8.0.7",
"@ng-bootstrap/ng-bootstrap": "^18.0.0",
"@ng-bootstrap/ng-bootstrap": "^19.0.1",
"@popperjs/core": "^2.11.7",
"@siemens/ngx-datatable": "^22.4.1",
"@swimlane/ngx-charts": "^22.0.0-alpha.0",
"@swimlane/ngx-charts": "^23.0.0-alpha.0",
"@tweenjs/tween.js": "^25.0.0",
"bootstrap": "^5.3.2",
"charts.css": "^1.1.0",
"file-saver": "^2.0.5",
"luxon": "^3.6.1",
"luxon": "^3.7.1",
"ng-circle-progress": "^1.7.1",
"ng-lazyload-image": "^9.1.3",
"ng-select2-component": "^17.2.4",
"ngx-color-picker": "^19.0.0",
"ngx-extended-pdf-viewer": "^23.0.0-alpha.7",
"ngx-color-picker": "^20.0.0",
"ngx-extended-pdf-viewer": "^24.1.0",
"ngx-file-drop": "^16.0.0",
"ngx-stars": "^1.6.5",
"ngx-toastr": "^19.0.0",
"nosleep.js": "^0.12.0",
"rxjs": "^7.8.2",
"screenfull": "^6.0.2",
"swiper": "^8.4.6",
"swiper": "^11.2.10",
"tslib": "^2.8.1",
"zone.js": "^0.15.0"
"zone.js": "^0.15.1"
},
"devDependencies": {
"@angular-eslint/builder": "^19.3.0",
"@angular-eslint/eslint-plugin": "^19.3.0",
"@angular-eslint/eslint-plugin-template": "^19.3.0",
"@angular-eslint/schematics": "^19.3.0",
"@angular-eslint/template-parser": "^19.3.0",
"@angular/build": "^19.2.6",
"@angular/cli": "^19.2.6",
"@angular/compiler-cli": "^19.2.5",
"@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": "^20.1.1",
"@angular/build": "^20.1.0",
"@angular/cli": "^20.1.0",
"@angular/compiler-cli": "^20.1.0",
"@types/d3": "^7.4.3",
"@types/file-saver": "^2.0.7",
"@types/luxon": "^3.6.2",
"@types/node": "^22.13.13",
"@typescript-eslint/eslint-plugin": "^8.28.0",
"@typescript-eslint/parser": "^8.28.0",
"eslint": "^9.23.0",
"@types/node": "^24.0.13",
"@typescript-eslint/eslint-plugin": "^8.36.0",
"@typescript-eslint/parser": "^8.36.0",
"eslint": "^9.31.0",
"jsonminify": "^0.4.2",
"karma-coverage": "~2.2.0",
"ts-node": "~10.9.1",
"typescript": "^5.5.4",
"typescript": "^5.8.3",
"webpack-bundle-analyzer": "^4.10.2"
}
}

View File

@ -263,13 +263,13 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
*/
darkMode = model<boolean>(true);
readingTimeLeftResource = resource({
request: () => ({
params: () => ({
chapterId: this.chapterId,
seriesId: this.seriesId,
pageNumber: this.pageNum(),
}),
loader: async ({ request }) => {
return this.readerService.getTimeLeftForChapter(this.seriesId, this.chapterId).toPromise();
loader: async ({params}) => {
return this.readerService.getTimeLeftForChapter(params.seriesId, params.chapterId).toPromise();
}
});

View File

@ -27,22 +27,22 @@
</div>
@if (items.length > 0) {
<div>
<swiper
[slidesPerView]="'auto'"
(init)="onSwiper($event)"
[freeMode]="true">
<swiper-container #swiperContainer
slides-per-view="auto"
free-mode="true"
(swiperprogress)="onProgress($event)">
@for(item of items; track item; let i = $index;) {
<ng-template swiperSlide>
<swiper-slide>
<ng-container [ngTemplateOutlet]="carouselItemTemplate" [ngTemplateOutletContext]="{ $implicit: item, idx: i }"></ng-container>
</ng-template>
</swiper-slide>
} @empty {
@if (alwaysShow) {
<ng-template swiperSlide>
<swiper-slide>
<ng-container [ngTemplateOutlet]="carouselItemTemplate"></ng-container>
</ng-template>
</swiper-slide>
}
}
</swiper>
</swiper-container>
</div>
}
</div>

View File

@ -29,15 +29,16 @@
}
}
::ng-deep .swiper-slide {
width: auto !important;
::ng-deep swiper-slide {
width: auto !important;
margin: 0 .25rem;
}
::ng-deep .swiper-wrapper {
::ng-deep swiper-container {
margin-bottom: 10px;
}
::ng-deep .last-carousel {
::ng-deep swiper-slide:last-child {
margin-bottom: 0;
}

View File

@ -3,26 +3,30 @@ import {
ChangeDetectorRef,
Component,
ContentChild,
CUSTOM_ELEMENTS_SCHEMA,
EventEmitter,
inject,
Input,
Output,
TemplateRef
} from '@angular/core';
import {Swiper, SwiperEvents} from 'swiper/types';
import {SwiperModule} from 'swiper/angular';
import {Swiper} from 'swiper/types';
import {register} from 'swiper/element/bundle';
import {NgClass, NgTemplateOutlet} from '@angular/common';
import {TranslocoDirective} from "@jsverse/transloco";
import {CardActionablesComponent} from "../../../_single-module/card-actionables/card-actionables.component";
import {ActionItem} from "../../../_services/action-factory.service";
import {SafeUrlPipe} from "../../../_pipes/safe-url.pipe";
register();
@Component({
selector: 'app-carousel-reel',
templateUrl: './carousel-reel.component.html',
styleUrls: ['./carousel-reel.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [NgClass, SwiperModule, NgTemplateOutlet, TranslocoDirective, CardActionablesComponent, SafeUrlPipe]
selector: 'app-carousel-reel',
templateUrl: './carousel-reel.component.html',
styleUrls: ['./carousel-reel.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [NgClass, NgTemplateOutlet, TranslocoDirective, CardActionablesComponent, SafeUrlPipe],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class CarouselReelComponent {
@ -75,11 +79,14 @@ export class CarouselReelComponent {
this.sectionClick.emit(this.title);
}
onSwiper(eventParams: Parameters<SwiperEvents['init']>) {
[this.swiper] = eventParams;
this.cdRef.detectChanges();
// Swiper new implementation makes it so we need to use a progress event to get initialized
onProgress(event: any) {
let progress = 0;
[this.swiper, progress] = event.detail;
this.cdRef.markForCheck()
}
performAction(action: ActionItem<any>) {
this.handleAction.emit(action);
}

View File

@ -31,7 +31,7 @@ import {PdfLayoutMode} from "../../../_models/preferences/pdf-layout-mode";
import {PdfScrollMode} from "../../../_models/preferences/pdf-scroll-mode";
import {PdfTheme} from "../../../_models/preferences/pdf-theme";
import {PdfSpreadMode} from "../../../_models/preferences/pdf-spread-mode";
import {SpreadType} from "ngx-extended-pdf-viewer/lib/options/spread-type";
import {SpreadType} from "node_modules/ngx-extended-pdf-viewer/lib/options/spread-type";
import {PdfScrollModeTypePipe} from "../../_pipe/pdf-scroll-mode.pipe";
import {PdfSpreadTypePipe} from "../../_pipe/pdf-spread-mode.pipe";
import {ReadingProfileService} from "../../../_services/reading-profile.service";

View File

@ -1,6 +1,6 @@
import {inject, Pipe, PipeTransform} from '@angular/core';
import {TranslocoService} from "@jsverse/transloco";
import {SpreadType} from "ngx-extended-pdf-viewer/lib/options/spread-type";
import {SpreadType} from "node_modules/ngx-extended-pdf-viewer/lib/options/spread-type";
@Pipe({
name: 'pdfSpreadType',

View File

@ -1,4 +1,4 @@
import {Injectable} from "@angular/core";
import {inject, Injectable} from "@angular/core";
import {HttpClient} from "@angular/common/http";
import {Translation, TranslocoLoader} from "@jsverse/transloco";
import cacheBusting from 'i18n-cache-busting.json'; // allowSyntheticDefaultImports must be true

View File

@ -8,7 +8,7 @@ import {AppRoutingModule} from './app/app-routing.module';
import {bootstrapApplication, BrowserModule, Title} from '@angular/platform-browser';
import {JwtInterceptor} from './app/_interceptors/jwt.interceptor';
import {ErrorInterceptor} from './app/_interceptors/error.interceptor';
import {HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi} from '@angular/common/http';
import {HTTP_INTERCEPTORS, provideHttpClient, withFetch, withInterceptorsFromDi} from '@angular/common/http';
import {provideTransloco, TranslocoConfig, TranslocoService} from "@jsverse/transloco";
import {environment} from "./environments/environment";
import {AccountService} from "./app/_services/account.service";
@ -20,9 +20,12 @@ import {distinctUntilChanged} from "rxjs/operators";
import {APP_BASE_HREF, PlatformLocation} from "@angular/common";
import {provideTranslocoPersistTranslations} from '@jsverse/transloco-persist-translations';
import {HttpLoader} from "./httpLoader";
import {register as registerSwiperElements} from 'swiper/element/bundle';
const disableAnimations = !('animate' in document.documentElement);
registerSwiperElements();
export function preloadUser(userService: AccountService, transloco: TranslocoService) {
return function() {
return userService.currentUser$.pipe(distinctUntilChanged(), switchMap((user) => {
@ -146,7 +149,7 @@ bootstrapApplication(AppComponent, {
useFactory: getBaseHref,
deps: [PlatformLocation]
},
provideHttpClient(withInterceptorsFromDi())
provideHttpClient(withInterceptorsFromDi(), withFetch())
]
} as ApplicationConfig)
.catch(err => console.error(err));

View File

@ -1,4 +1,4 @@
@use '../node_modules/swiper/swiper' as swiper;
@use 'swiper/swiper-bundle.min' as swiper;
@use './theme/variables' as theme;

View File

@ -14,7 +14,7 @@
"resolveJsonModule": true,
"declaration": false,
"experimentalDecorators": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "ES2022",
"module": "ES2022",
@ -22,7 +22,7 @@
"lib": [
"ES2022",
"dom"
],
]
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,