optimize song usage
This commit is contained in:
@@ -40,7 +40,12 @@
|
||||
@if (song.origin) {
|
||||
<div>Quelle: {{ song.origin }}</div>
|
||||
}
|
||||
<div>Wie oft verwendet: {{ songCount$ | async }}</div>
|
||||
<div
|
||||
[matTooltip]="songUsageTooltip$ | async"
|
||||
matTooltipPosition="above"
|
||||
>
|
||||
Wie oft verwendet: {{ songCount$ | async }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if (user$ | async; as user) {
|
||||
@@ -81,7 +86,7 @@
|
||||
Zu Veranstaltung hinzufügen
|
||||
</app-button>
|
||||
<mat-menu #menu="matMenu">
|
||||
@for (show of privateShows$|async; track show) {
|
||||
@for (show of privateShows$|async; track show.id) {
|
||||
<app-button (click)="addSongToShow(show, song)">
|
||||
{{ show.date.toDate() | date: "dd.MM.yyyy" }} {{ show.showType | showType }}
|
||||
</app-button>
|
||||
|
||||
@@ -3,6 +3,11 @@ import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
|
||||
import {SongComponent} from './song.component';
|
||||
import {of} from 'rxjs';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {SongService} from '../services/song.service';
|
||||
import {FileDataService} from '../services/file-data.service';
|
||||
import {UserService} from '../../../services/user/user.service';
|
||||
import {ShowService} from '../../shows/services/show.service';
|
||||
import {ShowSongService} from '../../shows/services/show-song.service';
|
||||
|
||||
describe('SongComponent', () => {
|
||||
let component: SongComponent;
|
||||
@@ -13,9 +18,28 @@ describe('SongComponent', () => {
|
||||
};
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
const songServiceSpy = jasmine.createSpyObj<SongService>('SongService', ['read$']);
|
||||
const fileDataServiceSpy = jasmine.createSpyObj<FileDataService>('FileDataService', ['read$']);
|
||||
const userServiceSpy = jasmine.createSpyObj<UserService>('UserService', ['incSongCount', 'decSongCount'], {
|
||||
user$: of({id: 'user-1', name: 'Benjamin', role: 'leader', chordMode: 'onlyFirst', songUsage: {'4711': 2}}),
|
||||
});
|
||||
const showServiceSpy = jasmine.createSpyObj<ShowService>('ShowService', ['list$', 'update$']);
|
||||
const showSongServiceSpy = jasmine.createSpyObj<ShowSongService>('ShowSongService', ['new$']);
|
||||
|
||||
songServiceSpy.read$.and.returnValue(of({id: '4711', title: 'Test Song', number: '1', text: '', showType: '', flags: ''} as never));
|
||||
fileDataServiceSpy.read$.and.returnValue(of([]));
|
||||
showServiceSpy.list$.and.returnValue(of([]));
|
||||
|
||||
void TestBed.configureTestingModule({
|
||||
imports: [SongComponent],
|
||||
providers: [{provide: ActivatedRoute, useValue: mockActivatedRoute}],
|
||||
providers: [
|
||||
{provide: ActivatedRoute, useValue: mockActivatedRoute},
|
||||
{provide: SongService, useValue: songServiceSpy},
|
||||
{provide: FileDataService, useValue: fileDataServiceSpy},
|
||||
{provide: UserService, useValue: userServiceSpy},
|
||||
{provide: ShowService, useValue: showServiceSpy},
|
||||
{provide: ShowSongService, useValue: showSongServiceSpy},
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import {SongTypePipe} from '../../../widget-modules/pipes/song-type-translater/s
|
||||
import {LegalOwnerPipe} from '../../../widget-modules/pipes/legal-owner-translator/legal-owner.pipe';
|
||||
import {StatusPipe} from '../../../widget-modules/pipes/status-translater/status.pipe';
|
||||
import {ShowTypePipe} from '../../../widget-modules/pipes/show-type-translater/show-type.pipe';
|
||||
import {MatTooltip} from '@angular/material/tooltip';
|
||||
|
||||
@Component({
|
||||
selector: 'app-song',
|
||||
@@ -48,6 +49,7 @@ import {ShowTypePipe} from '../../../widget-modules/pipes/show-type-translater/s
|
||||
LegalOwnerPipe,
|
||||
StatusPipe,
|
||||
ShowTypePipe,
|
||||
MatTooltip,
|
||||
],
|
||||
})
|
||||
export class SongComponent implements OnInit {
|
||||
@@ -63,10 +65,14 @@ export class SongComponent implements OnInit {
|
||||
public files$: Observable<File[] | null> | null = null;
|
||||
public user$: Observable<User | null> | null = null;
|
||||
public songCount$: Observable<number> | null = null;
|
||||
public songUsageShows$: Observable<Show[]> | null = null;
|
||||
public songUsageTooltip$: Observable<string> | null = null;
|
||||
public faEdit = faEdit;
|
||||
public faDelete = faTrash;
|
||||
public faFileCirclePlus = faFileCirclePlus;
|
||||
public privateShows$ = this.showService.list$().pipe(map(show => show.filter(_ => !_.published).sort((a, b) => b.date.toMillis() - a.date.toMillis())));
|
||||
private dateFormatter = new Intl.DateTimeFormat('de-DE', {day: '2-digit', month: '2-digit', year: 'numeric'});
|
||||
private showTypePipe = new ShowTypePipe();
|
||||
|
||||
public constructor() {
|
||||
const userService = this.userService;
|
||||
@@ -98,6 +104,33 @@ export class SongComponent implements OnInit {
|
||||
}),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
|
||||
this.songUsageShows$ = combineLatest([this.userService.user$, this.showService.list$(), song$]).pipe(
|
||||
map(([user, shows, song]) => {
|
||||
if (!user || !song) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return shows
|
||||
.filter(show => show.owner === user.id)
|
||||
.filter(show => (show.songIds ?? []).includes(song.id))
|
||||
.sort((a, b) => b.date.toMillis() - a.date.toMillis());
|
||||
})
|
||||
);
|
||||
|
||||
this.songUsageTooltip$ = combineLatest([this.songCount$, this.songUsageShows$]).pipe(
|
||||
map(([count, shows]) => {
|
||||
if (count === 0) {
|
||||
return 'Noch in keiner Show verwendet.';
|
||||
}
|
||||
|
||||
if (shows.length === 0) {
|
||||
return 'Verwendungen vorhanden, aber Show-Zuordnung noch nicht indexiert.';
|
||||
}
|
||||
|
||||
return shows.map(show => `${this.dateFormatter.format(show.date.toDate())} - ${this.showTypePipe.transform(show.showType)}`).join('\n');
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public getFlags = (flags: string): string[] => {
|
||||
|
||||
Reference in New Issue
Block a user