migrate angular 21 finalize

This commit is contained in:
2026-03-09 22:56:31 +01:00
parent 26c99a0dae
commit bb08e46b0c
63 changed files with 738 additions and 783 deletions

View File

@@ -1,4 +1,4 @@
import {Injectable} from '@angular/core';
import {Injectable, inject} from '@angular/core';
import {File} from './file';
import {Observable} from 'rxjs';
import {FileServer} from './fileServer';
@@ -8,7 +8,7 @@ import {DbService} from '../../../services/db.service';
providedIn: 'root',
})
export class FileDataService {
public constructor(private db: DbService) {}
private db = inject(DbService);
public async set(songId: string, file: FileServer): Promise<string> {
const songRef = this.db.doc('songs/' + songId);

View File

@@ -1,4 +1,4 @@
import {Injectable} from '@angular/core';
import {Injectable, inject} from '@angular/core';
import {deleteObject, getDownloadURL, ref, Storage} from '@angular/fire/storage';
import {from, Observable} from 'rxjs';
import {FileDataService} from './file-data.service';
@@ -7,10 +7,8 @@ import {FileDataService} from './file-data.service';
providedIn: 'root',
})
export class FileService {
public constructor(
private storage: Storage,
private fileDataService: FileDataService
) {}
private storage = inject(Storage);
private fileDataService = inject(FileDataService);
public getDownloadUrl(path: string): Observable<string> {
return from(getDownloadURL(ref(this.storage, path)));

View File

@@ -2,14 +2,14 @@ import {getScale, scaleMapping} from './key.helper';
describe('key.helper', () => {
it('should render Gb correctly', () => {
expect(scaleMapping['Gb']).toBe('G♭');
void expect(scaleMapping['Gb']).toBe('G♭');
});
it('should expose a sharp-based scale for D', () => {
expect(getScale('D')).toEqual(['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'H']);
void expect(getScale('D')).toEqual(['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'H']);
});
it('should keep flat-based spelling for Db', () => {
expect(getScale('Db')).toEqual(['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'B', 'H']);
void expect(getScale('Db')).toEqual(['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'B', 'H']);
});
});

View File

@@ -1,4 +1,4 @@
import {Injectable} from '@angular/core';
import {Injectable, inject} from '@angular/core';
import {Song} from './song';
import {Observable} from 'rxjs';
import {DbService} from '../../../services/db.service';
@@ -8,6 +8,8 @@ import {shareReplay, startWith} from 'rxjs/operators';
providedIn: 'root',
})
export class SongDataService {
private dbService = inject(DbService);
private collection = 'songs';
public list$: Observable<Song[]> = this.dbService.col$<Song>(this.collection).pipe(
startWith([] as Song[]), // immediate empty emit keeps UI responsive while first snapshot arrives
@@ -17,11 +19,6 @@ export class SongDataService {
})
);
public constructor(private dbService: DbService) {
// Warm the shared stream once at startup to avoid first-navigation delay.
// this.list$.subscribe();
}
public read$ = (songId: string): Observable<Song | null> => this.dbService.doc$(this.collection + '/' + songId);
public update$ = async (songId: string, data: Partial<Song>): Promise<void> => await this.dbService.doc(this.collection + '/' + songId).update(data);
public add = async (data: Partial<Song>): Promise<string> => (await this.dbService.col(this.collection).add(data)).id;

View File

@@ -1,4 +1,4 @@
import {Injectable} from '@angular/core';
import {Injectable, inject} from '@angular/core';
import {Observable} from 'rxjs';
import {SongService} from './song.service';
@@ -9,7 +9,7 @@ import {take} from 'rxjs/operators';
providedIn: 'root',
})
export class SongListResolver {
public constructor(private songService: SongService) {}
private songService = inject(SongService);
public resolve(): Observable<Song[]> {
return this.songService.list$().pipe(take(1));

View File

@@ -1,4 +1,4 @@
import {Injectable} from '@angular/core';
import {Injectable, inject} from '@angular/core';
import {firstValueFrom, Observable} from 'rxjs';
import {Song} from './song';
import {SongDataService} from './song-data.service';
@@ -16,21 +16,15 @@ export type SongLegalType = 'open' | 'allowed';
providedIn: 'root',
})
export class SongService {
private songDataService = inject(SongDataService);
private userService = inject(UserService);
public static TYPES: SongType[] = ['Praise', 'Worship', 'Misc'];
public static STATUS: SongStatus[] = ['draft', 'set', 'final'];
public static LEGAL_OWNER: SongLegalOwner[] = ['CCLI', 'other'];
public static LEGAL_TYPE: SongLegalType[] = ['open', 'allowed'];
// private list: Song[];
public constructor(
private songDataService: SongDataService,
private userService: UserService
) {
// importCCLI = (songs: Song[]) => this.updateFromCLI(songs);
}
public list$ = (): Observable<Song[]> => this.songDataService.list$; //.pipe(tap(_ => (this.list = _)));
public read$ = (songId: string): Observable<Song | null> => this.songDataService.read$(songId);
public read = (songId: string): Promise<Song | null> => firstValueFrom(this.read$(songId));

View File

@@ -1,4 +1,4 @@
import {Injectable} from '@angular/core';
import {Injectable, inject} from '@angular/core';
import {TransposeService} from './transpose.service';
import {TransposeMode} from './transpose-mode';
import {SectionType} from './section-type';
@@ -11,9 +11,9 @@ import {Line} from './line';
providedIn: 'root',
})
export class TextRenderingService {
private regexSection = /(Strophe|Refrain|Bridge)/;
private transposeService = inject(TransposeService);
public constructor(private transposeService: TransposeService) {}
private regexSection = /(Strophe|Refrain|Bridge)/;
public parse(text: string, transpose: TransposeMode | null, withComments = true): Section[] {
if (!text) {

View File

@@ -34,18 +34,18 @@ describe('TransposeService', () => {
const distance = service.getDistance('C', 'Db');
const map = service.getMap('C', 'Db', distance);
expect(distance).toBe(1);
expect(map?.['C']).toBe('Db');
expect(map?.['G']).toBe('Ab');
void expect(distance).toBe(1);
void expect(map?.['C']).toBe('Db');
void expect(map?.['G']).toBe('Ab');
});
it('should keep german B/H notation consistent', () => {
const distance = service.getDistance('H', 'C');
const map = service.getMap('H', 'C', distance);
expect(distance).toBe(1);
expect(map?.['H']).toBe('C');
expect(map?.['B']).toBe('C#');
void expect(distance).toBe(1);
void expect(map?.['H']).toBe('C');
void expect(map?.['B']).toBe('C#');
});
it('should render unknown chords as X', () => {
@@ -57,7 +57,7 @@ describe('TransposeService', () => {
const rendered = service.renderChords(line);
expect(rendered.text).toBe('Xsus4');
void expect(rendered.text).toBe('Xsus4');
});
it('should render unknown slash chords as X', () => {
@@ -69,7 +69,7 @@ describe('TransposeService', () => {
const rendered = service.renderChords(line);
expect(rendered.text).toBe('C/X');
void expect(rendered.text).toBe('C/X');
});
it('should transpose lines with long chord positions without truncating', () => {
@@ -81,7 +81,7 @@ describe('TransposeService', () => {
const rendered = service.renderChords(line);
expect(rendered.text.length).toBe(121);
expect(rendered.text.endsWith('C')).toBeTrue();
void expect(rendered.text.length).toBe(121);
void expect(rendered.text.endsWith('C')).toBeTrue();
});
});

View File

@@ -1,4 +1,4 @@
import {Injectable} from '@angular/core';
import {Injectable, inject} from '@angular/core';
import {Upload} from './upload';
import {FileDataService} from './file-data.service';
import {ref, Storage, uploadBytesResumable} from '@angular/fire/storage';
@@ -9,12 +9,8 @@ import {FileServer} from './fileServer';
providedIn: 'root',
})
export class UploadService extends FileBase {
public constructor(
private fileDataService: FileDataService,
private storage: Storage
) {
super();
}
private fileDataService = inject(FileDataService);
private storage = inject(Storage);
public pushUpload(songId: string, upload: Upload): void {
const directory = this.directory(songId);