This commit is contained in:
2026-03-15 12:50:33 +01:00
parent dd68a6b21d
commit d907c89eb6
36 changed files with 309 additions and 286 deletions

View File

@@ -19,7 +19,7 @@ export interface ShareDialogData {
export class ShareDialogComponent {
public data = inject<ShareDialogData>(MAT_DIALOG_DATA);
public qrCode: string;
public qrCode = '';
public constructor() {
const data = this.data;
@@ -35,10 +35,10 @@ export class ShareDialogComponent {
light: '#ffffff',
},
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-return
}).then(_ => (this.qrCode = _));
}).then((qrCode: string) => (this.qrCode = qrCode));
}
public async share() {
public async share(): Promise<void> {
if (navigator.clipboard) await navigator.clipboard.writeText(this.data.url);
if (navigator.share)

View File

@@ -87,10 +87,15 @@ export class EditComponent implements OnInit {
return;
}
await this.showService.update$(this.form.value.id, {
date: Timestamp.fromDate(this.form.value.date),
showType: this.form.value.showType,
const {id, date, showType} = this.form.getRawValue();
if (!id || !date || !showType) {
return;
}
await this.showService.update$(id, {
date: Timestamp.fromDate(date),
showType,
} as Partial<Show>);
await this.router.navigateByUrl(`/shows/${this.form.value.id ?? ''}`);
await this.router.navigateByUrl(`/shows/${id}`);
}
}

View File

@@ -1,6 +1,7 @@
import {Component, Input, inject} from '@angular/core';
import {Component, DestroyRef, Input, inject} from '@angular/core';
import {KeyValue} from '@angular/common';
import {ReactiveFormsModule, UntypedFormBuilder, UntypedFormGroup} from '@angular/forms';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
import {FormBuilder, FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms';
import {FilterValues} from './filter-values';
import {Show} from '../../services/show';
import {ShowService} from '../../services/show.service';
@@ -24,13 +25,18 @@ export class FilterComponent {
private showService = inject(ShowService);
private userService = inject(UserService);
private filterStore = inject(FilterStoreService);
private destroyRef = inject(DestroyRef);
@Input() public shows: Show[] = [];
public showTypePublic = ShowService.SHOW_TYPE_PUBLIC;
public showTypePrivate = ShowService.SHOW_TYPE_PRIVATE;
public filterFormGroup: UntypedFormGroup;
public filterFormGroup: FormGroup<{
time: FormControl<number>;
owner: FormControl<string | null>;
showType: FormControl<string | null>;
}>;
public times: KeyValue<number, string>[] = [
{key: 1, value: 'letzter Monat'},
{key: 3, value: 'letztes Quartal'},
@@ -41,15 +47,15 @@ export class FilterComponent {
public owners: {key: string; value: string}[] = [];
public constructor() {
const fb = inject(UntypedFormBuilder);
const fb = inject(FormBuilder);
this.filterFormGroup = fb.group({
time: 1,
owner: null,
showType: null,
time: fb.nonNullable.control(1),
owner: fb.control<string | null>(null),
showType: fb.control<string | null>(null),
});
this.filterStore.showFilter$.subscribe(filterValues => {
this.filterStore.showFilter$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(filterValues => {
this.filterFormGroup.patchValue(
{
time: filterValues.time,
@@ -60,11 +66,13 @@ export class FilterComponent {
);
});
this.filterFormGroup.controls.time.valueChanges.subscribe(_ => this.filterValueChanged('time', (_ as number) ?? 1));
this.filterFormGroup.controls.owner.valueChanges.subscribe(_ => this.filterValueChanged('owner', (_ as string | null) ?? ''));
this.filterFormGroup.controls.showType.valueChanges.subscribe(_ => this.filterValueChanged('showType', (_ as string | null) ?? ''));
this.filterFormGroup.controls.time.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => this.filterValueChanged('time', value));
this.filterFormGroup.controls.owner.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => this.filterValueChanged('owner', value ?? ''));
this.filterFormGroup.controls.showType.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => this.filterValueChanged('showType', value ?? ''));
this.owners$().subscribe(owners => (this.owners = owners));
this.owners$()
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(owners => (this.owners = owners));
}
public owners$ = (): Observable<{key: string; value: string}[]> => {
@@ -85,17 +93,15 @@ export class FilterComponent {
this.userService.getUserbyId$(ownerId).pipe(
map(user => ({
key: ownerId,
value: user?.name,
value: user?.name ?? ownerId,
}))
)
)
);
}),
map(owners => {
return owners.sort(dynamicSort('value'));
}),
map(owners => owners.sort(dynamicSort<{key: string; value: string}>('value'))),
distinctUntilChanged((left, right) => this.sameOwners(left, right)),
map(_ => _ as {key: string; value: string}[])
map(owners => owners as {key: string; value: string}[])
);
};

View File

@@ -3,7 +3,7 @@ import {ShowDataService} from '../services/show-data.service';
import {Observable} from 'rxjs';
import {Show} from '../services/show';
import {ShowService} from '../services/show.service';
import {ReactiveFormsModule, UntypedFormControl, UntypedFormGroup, Validators} from '@angular/forms';
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
import {Router} from '@angular/router';
import {faSave} from '@fortawesome/free-solid-svg-icons';
import {CardComponent} from '../../../widget-modules/components/card/card.component';
@@ -46,9 +46,9 @@ export class NewComponent implements OnInit {
public shows$: Observable<Show[]>;
public showTypePublic = ShowService.SHOW_TYPE_PUBLIC;
public showTypePrivate = ShowService.SHOW_TYPE_PRIVATE;
public form: UntypedFormGroup = new UntypedFormGroup({
date: new UntypedFormControl(null, Validators.required),
showType: new UntypedFormControl(null, Validators.required),
public form = new FormGroup({
date: new FormControl<Date | null>(null, Validators.required),
showType: new FormControl<string | null>(null, Validators.required),
});
public faSave = faSave;
@@ -68,7 +68,11 @@ export class NewComponent implements OnInit {
return;
}
const id = await this.showService.new$(this.form.value as Partial<Show>);
const {date, showType} = this.form.getRawValue();
const id = await this.showService.new$({
date,
showType,
} as unknown as Partial<Show>);
await this.router.navigateByUrl(`/shows/${id ?? ''}`);
}
}

View File

@@ -3,6 +3,7 @@ import {filter, map, shareReplay, switchMap, tap} from 'rxjs/operators';
import {ActivatedRoute, Router} from '@angular/router';
import {ShowService} from '../services/show.service';
import {Observable, of, Subscription} from 'rxjs';
import {take} from 'rxjs/operators';
import {Show} from '../services/show';
import {SongService} from '../../songs/services/song.service';
import {Song} from '../../songs/services/song';
@@ -112,12 +113,13 @@ export class ShowComponent implements OnInit, OnDestroy {
public faRestore = faMinimize;
public faMaximize = faMaximize;
public faNextSong = faChevronRight;
public currentTime: Date;
public currentTime!: Date;
private subs: Subscription[] = [];
private clockIntervalId: ReturnType<typeof setInterval> | null = null;
public ngOnInit(): void {
this.currentTime = new Date();
setInterval(() => {
this.clockIntervalId = setInterval(() => {
this.currentTime = new Date();
}, 10000);
this.show$ = this.activatedRoute.params.pipe(
@@ -155,6 +157,9 @@ export class ShowComponent implements OnInit, OnDestroy {
public ngOnDestroy(): void {
this.subs.forEach(_ => _.unsubscribe());
if (this.clockIntervalId) {
clearInterval(this.clockIntervalId);
}
}
public onZoomIn() {
@@ -172,7 +177,7 @@ export class ShowComponent implements OnInit, OnDestroy {
width: '350px',
});
dialogRef.afterClosed().subscribe((archive: boolean) => {
dialogRef.afterClosed().pipe(take(1)).subscribe((archive: boolean) => {
if (archive && this.showId != null) void this.showService.update$(this.showId, {archived});
});
}

View File

@@ -1,8 +1,9 @@
import {Component, Input, OnInit, ViewChild, inject} from '@angular/core';
import {Component, DestroyRef, Input, OnInit, ViewChild, inject} from '@angular/core';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
import {ShowSongService} from '../../services/show-song.service';
import {ShowSong} from '../../services/show-song';
import {getScale} from '../../../songs/services/key.helper';
import {ReactiveFormsModule, UntypedFormControl} from '@angular/forms';
import {FormControl, ReactiveFormsModule} from '@angular/forms';
import {ChordMode, SongTextComponent} from '../../../../widget-modules/components/song-text/song-text.component';
import {Show} from '../../services/show';
import {faEraser, faPenToSquare, faSave, faTrash} from '@fortawesome/free-solid-svg-icons';
@@ -42,6 +43,7 @@ import {CdkDragHandle} from '@angular/cdk/drag-drop';
})
export class SongComponent implements OnInit {
private showSongService = inject(ShowSongService);
private destroyRef = inject(DestroyRef);
@Input() public show: Show | null = null;
@Input() public showId: string | null = null;
@@ -54,11 +56,11 @@ export class SongComponent implements OnInit {
public faEdit = faPenToSquare;
public faSave = faSave;
public faEraser = faEraser;
public keyFormControl: UntypedFormControl = new UntypedFormControl();
public keyFormControl = new FormControl<string>('', {nonNullable: true});
public iSong: ShowSong | null = null;
public edit = false;
public editSongControl = new UntypedFormControl();
@ViewChild('option') private keyOptions: MatSelect;
public editSongControl = new FormControl<string | null>(null);
@ViewChild('option') private keyOptions!: MatSelect;
@Input()
public set showSong(song: ShowSong) {
@@ -68,8 +70,8 @@ export class SongComponent implements OnInit {
public ngOnInit(): void {
if (!this.iSong) return;
this.keyFormControl = new UntypedFormControl(this.iSong.key);
this.keyFormControl.valueChanges.subscribe((value: string) => {
this.keyFormControl = new FormControl<string>(this.iSong.key, {nonNullable: true});
this.keyFormControl.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => {
if (!this.showId || !this.iSong) return;
void this.showSongService.update$(this.showId, this.iSong.id, {key: value});
});