presenter function base
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
<div class="fullscreen">
|
||||
|
||||
<app-song-text [showSwitch]="false" [text]="song.text" chordMode="hide"></app-song-text>
|
||||
|
||||
</div>
|
||||
14
src/app/modules/presentation/monitor/monitor.component.less
Normal file
14
src/app/modules/presentation/monitor/monitor.component.less
Normal file
@@ -0,0 +1,14 @@
|
||||
.fullscreen {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: black;
|
||||
z-index: 1;
|
||||
|
||||
padding: 50px;
|
||||
|
||||
color: white;
|
||||
font-size: 30px;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {MonitorComponent} from './monitor.component';
|
||||
|
||||
describe('MonitorComponent', () => {
|
||||
let component: MonitorComponent;
|
||||
let fixture: ComponentFixture<MonitorComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [MonitorComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MonitorComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
39
src/app/modules/presentation/monitor/monitor.component.ts
Normal file
39
src/app/modules/presentation/monitor/monitor.component.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {map, switchMap, tap} from 'rxjs/operators';
|
||||
import {ShowService} from '../../shows/services/show.service';
|
||||
import {SongService} from '../../songs/services/song.service';
|
||||
import {Section, TextRenderingService} from '../../songs/services/text-rendering.service';
|
||||
import {Song} from '../../songs/services/song';
|
||||
|
||||
@Component({
|
||||
selector: 'app-monitor',
|
||||
templateUrl: './monitor.component.html',
|
||||
styleUrls: ['./monitor.component.less']
|
||||
})
|
||||
export class MonitorComponent implements OnInit {
|
||||
public song: Song;
|
||||
private index: number;
|
||||
private sections: Section[];
|
||||
|
||||
constructor(
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private showService: ShowService,
|
||||
private songService: SongService,
|
||||
private textRenderingService: TextRenderingService,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.activatedRoute.params.pipe(
|
||||
map(_ => _.showId),
|
||||
switchMap(_ => this.showService.read$(_)),
|
||||
tap(_ => this.index = _.presentationSection),
|
||||
switchMap(_ => this.songService.read(_.presentationSongId))
|
||||
).subscribe(_ => {
|
||||
this.song = _;
|
||||
this.sections = this.textRenderingService.parse(_.text);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
28
src/app/modules/presentation/presentation-routing.module.ts
Normal file
28
src/app/modules/presentation/presentation-routing.module.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import {NgModule} from '@angular/core';
|
||||
import {RouterModule, Routes} from '@angular/router';
|
||||
import {RemoteComponent} from './remote/remote.component';
|
||||
import {MonitorComponent} from './monitor/monitor.component';
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
redirectTo: 'remote'
|
||||
},
|
||||
{
|
||||
path: 'remote',
|
||||
component: RemoteComponent
|
||||
},
|
||||
{
|
||||
path: 'monitor/:showId',
|
||||
component: MonitorComponent
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class PresentationRoutingModule {
|
||||
}
|
||||
29
src/app/modules/presentation/presentation.module.ts
Normal file
29
src/app/modules/presentation/presentation.module.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import {NgModule} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
|
||||
import {PresentationRoutingModule} from './presentation-routing.module';
|
||||
import {MonitorComponent} from './monitor/monitor.component';
|
||||
import {RemoteComponent} from './remote/remote.component';
|
||||
import {CardModule} from '../../widget-modules/components/card/card.module';
|
||||
import {MatFormFieldModule} from '@angular/material/form-field';
|
||||
import {MatSelectModule} from '@angular/material/select';
|
||||
import {ShowTypeTranslaterModule} from '../../widget-modules/pipes/show-type-translater/show-type-translater.module';
|
||||
import {SectionTypeTranslatorModule} from '../../widget-modules/pipes/section-type-translator/section-type-translator.module';
|
||||
import {SongTextModule} from '../../widget-modules/components/song-text/song-text.module';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [MonitorComponent, RemoteComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
PresentationRoutingModule,
|
||||
CardModule,
|
||||
MatFormFieldModule,
|
||||
MatSelectModule,
|
||||
ShowTypeTranslaterModule,
|
||||
SectionTypeTranslatorModule,
|
||||
SongTextModule
|
||||
]
|
||||
})
|
||||
export class PresentationModule {
|
||||
}
|
||||
29
src/app/modules/presentation/remote/remote.component.html
Normal file
29
src/app/modules/presentation/remote/remote.component.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<div *ngIf="shows$|async as shows">
|
||||
<app-card>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Veranstaltung</mat-label>
|
||||
<mat-select (selectionChange)="onShowChanged($event)">
|
||||
<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>
|
||||
|
||||
<div *ngFor="let song of presentationSongs" class="song">
|
||||
<div class="title">{{song.title}}</div>
|
||||
<div *ngIf="show$|async as show" class="song-parts">
|
||||
<div (click)="onSectionClick(song.id, i)" *ngFor="let section of song.sections; index as i"
|
||||
[class.active]="show.presentationSongId===song.id && show.presentationSection===i"
|
||||
class="song-part">
|
||||
<div class="head">{{section.type|sectionType}} {{section.number + 1}}</div>
|
||||
<div class="fragment">{{getFirstLine(section)}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a [routerLink]="'/presentation/monitor/' + currentShowId">Presenter öffnen</a>
|
||||
|
||||
</app-card>
|
||||
|
||||
|
||||
</div>
|
||||
67
src/app/modules/presentation/remote/remote.component.less
Normal file
67
src/app/modules/presentation/remote/remote.component.less
Normal file
@@ -0,0 +1,67 @@
|
||||
@import "../../../../styles/shadow";
|
||||
|
||||
.song {
|
||||
background: #fffa;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
padding: 0 10px 10px 10px;
|
||||
|
||||
}
|
||||
|
||||
.song-parts {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
@media screen and (max-width: 860px) {
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
}
|
||||
@media screen and (max-width: 660px) {
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
}
|
||||
@media screen and (max-width: 460px) {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
grid-gap: 10px;
|
||||
}
|
||||
|
||||
.song-part {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
transition: 300ms all ease-in-out;
|
||||
cursor: pointer;
|
||||
.card-1;
|
||||
|
||||
&:hover {
|
||||
.card-2;
|
||||
}
|
||||
|
||||
&.active {
|
||||
.card-5;
|
||||
|
||||
.head {
|
||||
background: #4286f4;
|
||||
color: white;
|
||||
border-bottom: 0.5px solid #4286f4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.head {
|
||||
transition: 300ms all ease-in-out;
|
||||
background: #f4f4f4;
|
||||
border-bottom: 0.5px solid #ddd;
|
||||
padding: 10px;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.fragment {
|
||||
padding: 10px;
|
||||
}
|
||||
25
src/app/modules/presentation/remote/remote.component.spec.ts
Normal file
25
src/app/modules/presentation/remote/remote.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {RemoteComponent} from './remote.component';
|
||||
|
||||
describe('RemoteComponent', () => {
|
||||
let component: RemoteComponent;
|
||||
let fixture: ComponentFixture<RemoteComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [RemoteComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(RemoteComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
63
src/app/modules/presentation/remote/remote.component.ts
Normal file
63
src/app/modules/presentation/remote/remote.component.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {ShowDataService} from '../../shows/services/show-data.service';
|
||||
import {Observable} from 'rxjs';
|
||||
import {Show} from '../../shows/services/show';
|
||||
import {MatSelectChange} from '@angular/material/select';
|
||||
import {ShowSongService} from '../../shows/services/show-song.service';
|
||||
import {SongService} from '../../songs/services/song.service';
|
||||
import {Song} from '../../songs/services/song';
|
||||
import {Section, TextRenderingService} from '../../songs/services/text-rendering.service';
|
||||
|
||||
export interface PresentationSong {
|
||||
id: string;
|
||||
title: string;
|
||||
sections: Section[];
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-remote',
|
||||
templateUrl: './remote.component.html',
|
||||
styleUrls: ['./remote.component.less']
|
||||
})
|
||||
export class RemoteComponent {
|
||||
public shows$: Observable<Show[]>;
|
||||
public show$: Observable<Show>;
|
||||
public songs: Song[];
|
||||
public presentationSongs: PresentationSong[];
|
||||
public currentShowId: string;
|
||||
|
||||
constructor(
|
||||
private showDataService: ShowDataService,
|
||||
private showSongService: ShowSongService,
|
||||
private songService: SongService,
|
||||
private textRenderingService: TextRenderingService
|
||||
) {
|
||||
this.shows$ = showDataService.list$();
|
||||
songService.list$().subscribe(_ => this.songs = _);
|
||||
}
|
||||
|
||||
public onShowChanged(change: MatSelectChange): void {
|
||||
this.currentShowId = change.value;
|
||||
this.show$ = this.showDataService.read$(change.value);
|
||||
this.showSongService.list$(change.value).subscribe(_ => {
|
||||
this.presentationSongs = _
|
||||
.map(song => this.songs.filter(f => f.id == song.songId)[0])
|
||||
.map(song => ({
|
||||
id: song.id,
|
||||
title: song.title,
|
||||
sections: this.textRenderingService.parse(song.text)
|
||||
}))
|
||||
});
|
||||
}
|
||||
|
||||
public getFirstLine(section: Section): string {
|
||||
return section.lines.filter(_ => _.type === 1)[0].text;
|
||||
}
|
||||
|
||||
public async onSectionClick(id: string, index: number): Promise<void> {
|
||||
await this.showDataService.update(this.currentShowId, {
|
||||
presentationSongId: id,
|
||||
presentationSection: index
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
|
||||
import {PresentationService} from './presentation.service';
|
||||
|
||||
describe('PresentationService', () => {
|
||||
let service: PresentationService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(PresentationService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class PresentationService {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user