optimize remote #3
This commit is contained in:
@@ -2,6 +2,7 @@ import {NgModule} from '@angular/core';
|
|||||||
import {RouterModule, Routes} from '@angular/router';
|
import {RouterModule, Routes} from '@angular/router';
|
||||||
import {RemoteComponent} from './remote/remote.component';
|
import {RemoteComponent} from './remote/remote.component';
|
||||||
import {MonitorComponent} from './monitor/monitor.component';
|
import {MonitorComponent} from './monitor/monitor.component';
|
||||||
|
import {SelectComponent} from './select/select.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
@@ -13,6 +14,10 @@ const routes: Routes = [
|
|||||||
path: 'remote',
|
path: 'remote',
|
||||||
component: RemoteComponent,
|
component: RemoteComponent,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'select',
|
||||||
|
component: SelectComponent,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'monitor',
|
path: 'monitor',
|
||||||
component: MonitorComponent,
|
component: MonitorComponent,
|
||||||
|
|||||||
@@ -17,9 +17,10 @@ import {MatSliderModule} from '@angular/material/slider';
|
|||||||
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||||
import {AddSongModule} from '../../widget-modules/components/add-song/add-song.module';
|
import {AddSongModule} from '../../widget-modules/components/add-song/add-song.module';
|
||||||
import {LogoComponent} from './monitor/logo/logo.component';
|
import {LogoComponent} from './monitor/logo/logo.component';
|
||||||
|
import {SelectComponent} from './select/select.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [MonitorComponent, RemoteComponent, LegalComponent, LogoComponent],
|
declarations: [MonitorComponent, RemoteComponent, LegalComponent, LogoComponent, SelectComponent],
|
||||||
exports: [RemoteComponent],
|
exports: [RemoteComponent],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
|||||||
@@ -1,18 +1,6 @@
|
|||||||
<div *ngIf="shows$ | async as shows">
|
<div *ngIf="show">
|
||||||
<app-card>
|
<app-card [heading]="show.showType | showType" [subheading]="show.date.toDate() | date:'dd.MM.yyyy'"
|
||||||
<p *ngIf="!shows.length">
|
closeLink="/presentation/select" [closeIcon]="faIcon">
|
||||||
Es ist derzeit keine Veranstaltung vorhanden
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<mat-form-field *ngIf="shows.length > 0" @fade appearance="outline">
|
|
||||||
<mat-label>Veranstaltung</mat-label>
|
|
||||||
<mat-select [formControl]="showControl">
|
|
||||||
<mat-option *ngFor="let show of shows" [value]="show.id">
|
|
||||||
{{ show.showType | showType }},
|
|
||||||
{{ show.date.toDate() | date: "dd.MM.yyyy" }}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<ng-container *ngIf="!progress">
|
<ng-container *ngIf="!progress">
|
||||||
<div class="song">
|
<div class="song">
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component} from '@angular/core';
|
import {ChangeDetectionStrategy, ChangeDetectorRef, Component} from '@angular/core';
|
||||||
import {combineLatest, Observable} from 'rxjs';
|
import {combineLatest} from 'rxjs';
|
||||||
import {PresentationBackground, Show} from '../../shows/services/show';
|
import {PresentationBackground, Show} from '../../shows/services/show';
|
||||||
import {ShowSongService} from '../../shows/services/show-song.service';
|
import {ShowSongService} from '../../shows/services/show-song.service';
|
||||||
import {SongService} from '../../songs/services/song.service';
|
import {SongService} from '../../songs/services/song.service';
|
||||||
import {faDesktop} from '@fortawesome/free-solid-svg-icons';
|
import {faDesktop, faRepeat} from '@fortawesome/free-solid-svg-icons';
|
||||||
import {ShowService} from '../../shows/services/show.service';
|
import {ShowService} from '../../shows/services/show.service';
|
||||||
import {ShowSong} from '../../shows/services/show-song';
|
import {ShowSong} from '../../shows/services/show-song';
|
||||||
import {GlobalSettingsService} from '../../../services/global-settings.service';
|
import {GlobalSettingsService} from '../../../services/global-settings.service';
|
||||||
import {UntypedFormControl} from '@angular/forms';
|
import {filter, map} from 'rxjs/operators';
|
||||||
import {debounceTime, distinctUntilChanged, filter, map} from 'rxjs/operators';
|
|
||||||
import {fade} from '../../../animations';
|
import {fade} from '../../../animations';
|
||||||
import {TextRenderingService} from '../../songs/services/text-rendering.service';
|
import {TextRenderingService} from '../../songs/services/text-rendering.service';
|
||||||
import {Section} from '../../songs/services/section';
|
import {Section} from '../../songs/services/section';
|
||||||
@@ -28,16 +27,15 @@ export interface PresentationSong {
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class RemoteComponent {
|
export class RemoteComponent {
|
||||||
public shows$: Observable<Show[]>;
|
|
||||||
public show: Show | null = null;
|
public show: Show | null = null;
|
||||||
public showSongs: ShowSong[] = [];
|
public showSongs: ShowSong[] = [];
|
||||||
public songs$ = this.songService.list$();
|
public songs$ = this.songService.list$();
|
||||||
public presentationSongs: PresentationSong[] = [];
|
public presentationSongs: PresentationSong[] = [];
|
||||||
public currentShowId: string | null = null;
|
public currentShowId: string | null = null;
|
||||||
public progress = false;
|
public progress = false;
|
||||||
|
public faIcon = faRepeat;
|
||||||
|
|
||||||
public faDesktop = faDesktop;
|
public faDesktop = faDesktop;
|
||||||
public showControl = new UntypedFormControl();
|
|
||||||
|
|
||||||
public trackBy(index: number, item: PresentationSong): string {
|
public trackBy(index: number, item: PresentationSong): string {
|
||||||
return item.id;
|
return item.id;
|
||||||
@@ -51,48 +49,29 @@ export class RemoteComponent {
|
|||||||
private globalSettingsService: GlobalSettingsService,
|
private globalSettingsService: GlobalSettingsService,
|
||||||
private cRef: ChangeDetectorRef
|
private cRef: ChangeDetectorRef
|
||||||
) {
|
) {
|
||||||
this.shows$ = showService
|
|
||||||
.list$(true)
|
|
||||||
.pipe(map(_ => _.filter(_ => _.date.toDate() > new Date(new Date().setMonth(new Date().getMonth() - 1))).sort((a, b) => (b.date < a.date ? -1 : b.date > a.date ? 1 : 0))));
|
|
||||||
|
|
||||||
globalSettingsService.get$
|
globalSettingsService.get$
|
||||||
.pipe(
|
.pipe(
|
||||||
filter(_ => !!_),
|
filter(_ => !!_),
|
||||||
map(_ => _ as GlobalSettings),
|
map(_ => _ as GlobalSettings),
|
||||||
map(_ => _.currentShow),
|
map(_ => _.currentShow)
|
||||||
distinctUntilChanged()
|
|
||||||
)
|
)
|
||||||
.subscribe(_ => {
|
.subscribe(_ => {
|
||||||
this.showControl.setValue(_, {emitEvent: false});
|
void this.onShowChanged(_);
|
||||||
void this.onShowChanged(_, false);
|
|
||||||
});
|
});
|
||||||
this.showControl.valueChanges.subscribe((value: string) => void this.onShowChanged(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async onShowChanged(change: string, updateShow = true): Promise<void> {
|
public onShowChanged(change: string): void {
|
||||||
this.presentationSongs = [];
|
combineLatest([this.showService.read$(change), this.showSongService.list$(change)]).subscribe(([show, list]) => {
|
||||||
this.cRef.markForCheck();
|
this.showSongs = list;
|
||||||
|
this.show = show;
|
||||||
if (updateShow) {
|
const presentationSongs = list.map(song => ({
|
||||||
await this.globalSettingsService.set({currentShow: change});
|
id: song.id,
|
||||||
await this.showService.update$(change, {presentationSongId: 'title'});
|
title: song.title,
|
||||||
}
|
sections: this.textRenderingService.parse(song.text, null),
|
||||||
|
}));
|
||||||
this.currentShowId = change;
|
this.presentationSongs = show?.order.map(_ => presentationSongs.filter(f => f.id === _)[0]) ?? [];
|
||||||
|
this.cRef.markForCheck();
|
||||||
combineLatest([this.showService.read$(change), this.showSongService.list$(change)])
|
});
|
||||||
.pipe(debounceTime(300))
|
|
||||||
.subscribe(([show, list]) => {
|
|
||||||
this.showSongs = list;
|
|
||||||
this.show = show;
|
|
||||||
const presentationSongs = list.map(song => ({
|
|
||||||
id: song.id,
|
|
||||||
title: song.title,
|
|
||||||
sections: this.textRenderingService.parse(song.text, null),
|
|
||||||
}));
|
|
||||||
this.presentationSongs = show?.order.map(_ => presentationSongs.filter(f => f.id === _)[0]) ?? [];
|
|
||||||
this.cRef.markForCheck();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getFirstLine(section: Section): string {
|
public getFirstLine(section: Section): string {
|
||||||
|
|||||||
14
src/app/modules/presentation/select/select.component.html
Normal file
14
src/app/modules/presentation/select/select.component.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<div *ngIf="visible && shows$ | async as shows" @fade>
|
||||||
|
<app-card heading="Bitte eine Veranstaltung auswählen">
|
||||||
|
<p *ngIf="!shows.length">
|
||||||
|
Es ist derzeit keine Veranstaltung vorhanden
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div *ngIf="shows.length>0" class="list">
|
||||||
|
<button mat-stroked-button *ngFor="let show of shows" (click)="selectShow(show)">
|
||||||
|
{{ show.showType | showType }},
|
||||||
|
{{ show.date.toDate() | date: "dd.MM.yyyy" }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</app-card>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.list {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
33
src/app/modules/presentation/select/select.component.ts
Normal file
33
src/app/modules/presentation/select/select.component.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {map} from 'rxjs/operators';
|
||||||
|
import {ShowService} from '../../shows/services/show.service';
|
||||||
|
import {Show} from '../../shows/services/show';
|
||||||
|
import {GlobalSettingsService} from '../../../services/global-settings.service';
|
||||||
|
import {Router} from '@angular/router';
|
||||||
|
import {fade} from '../../../animations';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-select',
|
||||||
|
templateUrl: './select.component.html',
|
||||||
|
styleUrls: ['./select.component.less'],
|
||||||
|
animations: [fade],
|
||||||
|
})
|
||||||
|
export class SelectComponent implements OnInit {
|
||||||
|
public constructor(private showService: ShowService, private globalSettingsService: GlobalSettingsService, private router: Router) {}
|
||||||
|
public visible = false;
|
||||||
|
|
||||||
|
public shows$ = this.showService
|
||||||
|
.list$(true)
|
||||||
|
.pipe(map(_ => _.filter(_ => _.date.toDate() > new Date(new Date().setMonth(new Date().getMonth() - 1))).sort((a, b) => (b.date < a.date ? -1 : b.date > a.date ? 1 : 0))));
|
||||||
|
|
||||||
|
public async selectShow(show: Show) {
|
||||||
|
this.visible = false;
|
||||||
|
await this.globalSettingsService.set({currentShow: show.id});
|
||||||
|
await this.showService.update$(show.id, {presentationSongId: 'title'});
|
||||||
|
await this.router.navigateByUrl('/presentation/remote');
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnInit(): void {
|
||||||
|
this.visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,8 +5,9 @@
|
|||||||
class="btn-close"
|
class="btn-close"
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
>
|
>
|
||||||
<fa-icon [icon]="faClose"></fa-icon>
|
<fa-icon [icon]="closeIcon"></fa-icon>
|
||||||
</button>
|
</button>
|
||||||
<div *ngIf="heading" class="heading">{{ heading }}</div>
|
<div *ngIf="heading" class="heading">{{ heading }}</div>
|
||||||
|
<div *ngIf="subheading" class="subheading">{{ subheading }}</div>
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -32,8 +32,18 @@
|
|||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
}
|
}
|
||||||
|
.subheading {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
margin-right: 20px;
|
||||||
|
opacity: 0.7;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.padding .heading {
|
.padding .heading, .padding .subheading {
|
||||||
|
display: inline-block;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {faTimes} from '@fortawesome/free-solid-svg-icons';
|
|||||||
export class CardComponent {
|
export class CardComponent {
|
||||||
@Input() public padding = true;
|
@Input() public padding = true;
|
||||||
@Input() public heading: string | null = null;
|
@Input() public heading: string | null = null;
|
||||||
|
@Input() public subheading: string | null = null;
|
||||||
@Input() public closeLink: string | null = null;
|
@Input() public closeLink: string | null = null;
|
||||||
|
@Input() public closeIcon = faTimes;
|
||||||
public faClose = faTimes;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user