Angular 16 (#2007)

* Removed adv, which isn't needed.

* Updated zone

* Updated to angular 16

* Updated to angular 16 (partially)

* Updated to angular 16

* Package update for Angular 16 (and other dependencies) is complete.

* Replaced all takeUntil(this.onDestroy) with new takeUntilDestroyed()

* Updated all inputs that have ! to be required and deleted all unit tests.

* Corrected how takeUntilDestroyed() is supposed to be implemented.
This commit is contained in:
Joe Milazzo 2023-05-21 12:30:32 -05:00 committed by GitHub
parent 9bc8361381
commit 9c06cccd35
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
87 changed files with 3964 additions and 20426 deletions

View file

@ -1,9 +1,20 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, TemplateRef } from '@angular/core';
import {
Component,
DestroyRef,
EventEmitter,
inject,
Input,
OnDestroy,
OnInit,
Output,
TemplateRef
} from '@angular/core';
import { NgbOffcanvas } from '@ng-bootstrap/ng-bootstrap';
import { Subject, takeUntil } from 'rxjs';
import { Breakpoint, UtilityService } from 'src/app/shared/_services/utility.service';
import { NavService } from 'src/app/_services/nav.service';
import { ToggleService } from 'src/app/_services/toggle.service';
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
/**
* This should go on all pages which have the side nav present and is not Settings related.
@ -14,7 +25,7 @@ import { ToggleService } from 'src/app/_services/toggle.service';
templateUrl: './side-nav-companion-bar.component.html',
styleUrls: ['./side-nav-companion-bar.component.scss']
})
export class SideNavCompanionBarComponent implements OnInit, OnDestroy {
export class SideNavCompanionBarComponent implements OnInit {
/**
* If the page should show a filter
*/
@ -34,7 +45,7 @@ export class SideNavCompanionBarComponent implements OnInit, OnDestroy {
*/
@Input() filterActive: boolean = false;
@Input() extraDrawer!: TemplateRef<any>;
@Input() extraDrawer!: TemplateRef<any>;
@Output() filterOpen: EventEmitter<boolean> = new EventEmitter();
@ -42,9 +53,9 @@ export class SideNavCompanionBarComponent implements OnInit, OnDestroy {
isFilterOpen = false;
isExtrasOpen = false;
private onDestroy: Subject<void> = new Subject();
private readonly destroyRef = inject(DestroyRef);
constructor(private navService: NavService, private utilityService: UtilityService, public toggleService: ToggleService,
constructor(private navService: NavService, private utilityService: UtilityService, public toggleService: ToggleService,
private offcanvasService: NgbOffcanvas) {
}
@ -52,7 +63,7 @@ export class SideNavCompanionBarComponent implements OnInit, OnDestroy {
this.isFilterOpen = this.filterOpenByDefault;
// If user opens side nav while filter is open on mobile, then collapse filter (as it doesn't render well) TODO: Change this when we have new drawer
this.navService.sideNavCollapsed$.pipe(takeUntil(this.onDestroy)).subscribe(sideNavCollapsed => {
this.navService.sideNavCollapsed$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(sideNavCollapsed => {
if (this.isFilterOpen && sideNavCollapsed && this.utilityService.getActiveBreakpoint() < Breakpoint.Tablet) {
this.isFilterOpen = false;
this.filterOpen.emit(this.isFilterOpen);
@ -60,11 +71,6 @@ export class SideNavCompanionBarComponent implements OnInit, OnDestroy {
});
}
ngOnDestroy(): void {
this.onDestroy.next();
this.onDestroy.complete();
}
toggleFilter() {
this.isFilterOpen = !this.isFilterOpen;
this.filterOpen.emit(this.isFilterOpen);

View file

@ -1,7 +1,17 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
DestroyRef,
inject,
Input,
OnDestroy,
OnInit
} from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { filter, map, Subject, takeUntil } from 'rxjs';
import { NavService } from 'src/app/_services/nav.service';
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
@Component({
@ -10,7 +20,7 @@ import { NavService } from 'src/app/_services/nav.service';
styleUrls: ['./side-nav-item.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SideNavItemComponent implements OnInit, OnDestroy {
export class SideNavItemComponent implements OnInit {
/**
* Icon to display next to item. ie) 'fa-home'
*/
@ -31,35 +41,30 @@ export class SideNavItemComponent implements OnInit, OnDestroy {
@Input() external: boolean = false;
@Input() comparisonMethod: 'startsWith' | 'equals' = 'equals';
private readonly destroyRef = inject(DestroyRef);
highlighted = false;
private onDestroy: Subject<void> = new Subject();
constructor(public navService: NavService, private router: Router, private readonly cdRef: ChangeDetectorRef) {
router.events
.pipe(filter(event => event instanceof NavigationEnd),
takeUntil(this.onDestroy),
.pipe(filter(event => event instanceof NavigationEnd),
takeUntilDestroyed(this.destroyRef),
map(evt => evt as NavigationEnd))
.subscribe((evt: NavigationEnd) => {
this.updateHightlight(evt.url.split('?')[0]);
this.updateHighlight(evt.url.split('?')[0]);
});
}
ngOnInit(): void {
setTimeout(() => {
this.updateHightlight(this.router.url.split('?')[0]);
this.updateHighlight(this.router.url.split('?')[0]);
}, 100);
}
ngOnDestroy(): void {
this.onDestroy.next();
this.onDestroy.complete();
}
updateHightlight(page: string) {
updateHighlight(page: string) {
if (this.link === undefined) {
this.highlighted = false;
this.cdRef.markForCheck();

View file

@ -1,4 +1,12 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
DestroyRef,
inject,
OnDestroy,
OnInit
} from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { Subject } from 'rxjs';
@ -14,6 +22,7 @@ import { Action, ActionFactoryService, ActionItem } from '../../../_services/act
import { ActionService } from '../../../_services/action.service';
import { LibraryService } from '../../../_services/library.service';
import { NavService } from '../../../_services/nav.service';
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
@Component({
selector: 'app-side-nav',
@ -21,8 +30,9 @@ import { NavService } from '../../../_services/nav.service';
styleUrls: ['./side-nav.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SideNavComponent implements OnInit, OnDestroy {
export class SideNavComponent implements OnInit {
private readonly destroyRef = inject(DestroyRef);
libraries: Library[] = [];
actions: ActionItem<Library>[] = [];
readingListActions = [{action: Action.Import, title: 'Import CBL', children: [], requiresAdmin: true, callback: this.importCbl.bind(this)}];
@ -32,18 +42,16 @@ export class SideNavComponent implements OnInit, OnDestroy {
return library.name.toLowerCase().indexOf((this.filterQuery || '').toLowerCase()) >= 0;
}
private onDestroy: Subject<void> = new Subject();
constructor(public accountService: AccountService, private libraryService: LibraryService,
public utilityService: UtilityService, private messageHub: MessageHubService,
private actionFactoryService: ActionFactoryService, private actionService: ActionService,
private actionFactoryService: ActionFactoryService, private actionService: ActionService,
public navService: NavService, private router: Router, private readonly cdRef: ChangeDetectorRef,
private ngbModal: NgbModal, private imageService: ImageService) {
this.router.events.pipe(
filter(event => event instanceof NavigationEnd),
takeUntil(this.onDestroy),
filter(event => event instanceof NavigationEnd),
takeUntilDestroyed(this.destroyRef),
map(evt => evt as NavigationEnd),
filter(() => this.utilityService.getActiveBreakpoint() < Breakpoint.Tablet))
.subscribe((evt: NavigationEnd) => {
@ -68,7 +76,7 @@ export class SideNavComponent implements OnInit, OnDestroy {
this.cdRef.markForCheck();
});
this.messageHub.messages$.pipe(takeUntil(this.onDestroy), filter(event => event.event === EVENTS.LibraryModified)).subscribe(event => {
this.messageHub.messages$.pipe(takeUntilDestroyed(this.destroyRef), filter(event => event.event === EVENTS.LibraryModified)).subscribe(event => {
this.libraryService.getLibraries().pipe(take(1), shareReplay()).subscribe((libraries: Library[]) => {
this.libraries = [...libraries];
this.cdRef.markForCheck();
@ -76,11 +84,6 @@ export class SideNavComponent implements OnInit, OnDestroy {
});
}
ngOnDestroy(): void {
this.onDestroy.next();
this.onDestroy.complete();
}
handleAction(action: ActionItem<Library>, library: Library) {
switch (action.action) {
case(Action.Scan):
@ -129,4 +132,4 @@ export class SideNavComponent implements OnInit, OnDestroy {
this.navService.toggleSideNav();
}
}
}

View file

@ -1,4 +1,13 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
DestroyRef,
inject,
Input,
OnDestroy,
OnInit
} from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ToastrService } from 'ngx-toastr';
@ -11,6 +20,7 @@ import { Library, LibraryType } from 'src/app/_models/library';
import { ImageService } from 'src/app/_services/image.service';
import { LibraryService } from 'src/app/_services/library.service';
import { UploadService } from 'src/app/_services/upload.service';
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
enum TabID {
General = 'General',
@ -32,9 +42,10 @@ enum StepID {
styleUrls: ['./library-settings-modal.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class LibrarySettingsModalComponent implements OnInit, OnDestroy {
export class LibrarySettingsModalComponent implements OnInit {
@Input() library!: Library;
@Input({required: true}) library!: Library;
private readonly destroyRef = inject(DestroyRef);
active = TabID.General;
imageUrls: Array<string> = [];
@ -54,17 +65,16 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy {
selectedFolders: string[] = [];
madeChanges = false;
libraryTypes: string[] = []
isAddLibrary = false;
setupStep = StepID.General;
private readonly onDestroy = new Subject<void>();
get Breakpoint() { return Breakpoint; }
get TabID() { return TabID; }
get StepID() { return StepID; }
constructor(public utilityService: UtilityService, private uploadService: UploadService, private modalService: NgbModal,
private settingService: SettingsService, public modal: NgbActiveModal, private confirmService: ConfirmService,
private settingService: SettingsService, public modal: NgbActiveModal, private confirmService: ConfirmService,
private libraryService: LibraryService, private toastr: ToastrService, private readonly cdRef: ChangeDetectorRef,
private imageService: ImageService) { }
@ -87,7 +97,7 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy {
}
this.libraryForm.get('name')?.valueChanges.pipe(
debounceTime(100),
debounceTime(100),
distinctUntilChanged(),
switchMap(name => this.libraryService.libraryNameExists(name)),
tap(exists => {
@ -95,23 +105,17 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy {
if (!exists || isExistingName) {
this.libraryForm.get('name')?.setErrors(null);
} else {
this.libraryForm.get('name')?.setErrors({duplicateName: true})
this.libraryForm.get('name')?.setErrors({duplicateName: true})
}
this.cdRef.markForCheck();
}),
takeUntil(this.onDestroy)
takeUntilDestroyed(this.destroyRef)
).subscribe();
this.setValues();
}
ngOnDestroy() {
this.onDestroy.next();
this.onDestroy.complete();
}
setValues() {
if (this.library !== undefined) {
this.libraryForm.get('name')?.setValue(this.library.name);
@ -159,7 +163,7 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy {
model.type = parseInt(model.type, 10);
if (model.type !== this.library.type) {
if (!await this.confirmService.confirm(`Changing library type will trigger a new scan with different parsing rules and may lead to
if (!await this.confirmService.confirm(`Changing library type will trigger a new scan with different parsing rules and may lead to
series being re-created and hence you may loose progress and bookmarks. You should backup before you do this. Are you sure you want to continue?`)) return;
}
@ -221,7 +225,7 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy {
isNextDisabled() {
switch (this.setupStep) {
case StepID.General:
case StepID.General:
return this.libraryForm.get('name')?.invalid || this.libraryForm.get('type')?.invalid;
case StepID.Folder:
return this.selectedFolders.length === 0;