Add notes to stage, fix CORS issue

- Use a ServiceItem object rather than just slides to transfer more information at one time
- Add notes to stage view
- Fix CORS issue
This commit is contained in:
Raoul Snyman 2020-07-21 16:26:34 -07:00
parent 29041b7f1e
commit 2d10b7a363
Signed by: raoul
GPG Key ID: F55BCED79626AE9C
8 changed files with 118 additions and 51 deletions

View File

@ -28,6 +28,7 @@ import { SlidesComponent } from './components/slides/slides.component';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { ChordViewComponent } from './components/chord-view/chord-view.component'; import { ChordViewComponent } from './components/chord-view/chord-view.component';
import { StageViewComponent } from './components/stage-view/stage-view.component'; import { StageViewComponent } from './components/stage-view/stage-view.component';
import { Nl2BrPipe } from './components/stage-view/nl2br.pipe';
import { MainViewComponent } from './components/main-view/main-view.component'; import { MainViewComponent } from './components/main-view/main-view.component';
import { ChordProPipe } from './components/chord-view/chordpro.pipe'; import { ChordProPipe } from './components/chord-view/chordpro.pipe';
import { LoginComponent } from './components/login/login.component'; import { LoginComponent } from './components/login/login.component';
@ -39,6 +40,7 @@ import { ThemesComponent } from './components/themes/themes.component';
AppComponent, AppComponent,
ChordViewComponent, ChordViewComponent,
StageViewComponent, StageViewComponent,
Nl2BrPipe,
MainViewComponent, MainViewComponent,
ChordProPipe, ChordProPipe,
LoginComponent, LoginComponent,

View File

@ -18,11 +18,25 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
width: 30%;
} }
.time { .time {
font-size: 2rem; font-size: 3rem;
color: gray; color: yellow;
text-align: right;
}
.notes {
margin-top: 1em;
font-size: 3rem;
line-height: 3rem;
color: salmon;
text-align: right;
}
.close {
text-align: right;
} }
.tags { .tags {
@ -31,12 +45,13 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: flex-start; justify-content: flex-start;
color: gray; color: green;
font-size: 4rem; font-size: 4rem;
span { span {
margin-left: 1rem; margin-left: 1rem;
&.active { &.active {
color: white; color: lightgreen;
font-weight: bold;
} }
} }
} }
@ -57,7 +72,7 @@
.nextSlides { .nextSlides {
font-size: 2rem; font-size: 2rem;
margin-top: 1rem; margin-top: 1rem;
color: gray; color: grey;
.slide { .slide {
font-size: 2rem; font-size: 2rem;
} }

View File

@ -27,6 +27,13 @@ export class SlidesComponent implements OnInit {
} }
getSlides() { getSlides() {
this.openlpService.getItemSlides().subscribe(slides => this.slides = slides); this.openlpService.getServiceItem().subscribe(serviceItem => {
if (serviceItem instanceof Array) {
this.slides = serviceItem;
}
else {
this.slides = serviceItem.slides;
}
});
} }
} }

View File

@ -0,0 +1,17 @@
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
@Pipe({name: 'nl2br'})
export class Nl2BrPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) { }
transform(value: string): string|SafeHtml {
if (!value) {
return value;
}
if (typeof value !== 'string') {
throw Error(`Invalid pipe argument: '${value}' for pipe 'Nl2BrPipe'`);
}
return this.sanitizer.bypassSecurityTrustHtml(value.replace(/(?:\r\n|\r|\n)/g, '<br>'));
}
}

View File

@ -15,7 +15,10 @@
</div> </div>
</div> </div>
<div class="sidebar"> <div class="sidebar">
<div class="top">
<div class="time">{{ time|date:'HH:mm' }}</div> <div class="time">{{ time|date:'HH:mm' }}</div>
<button mat-raised-button class="closeButton" routerLink="/">Close</button> <div class="notes" [innerHTML]="notes|nl2br"></div>
</div>
<div class="close"><button mat-raised-button class="closeButton" routerLink="/">Close</button></div>
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { OpenLPService } from '../../openlp.service'; import { OpenLPService } from '../../openlp.service';
import { Slide } from '../../responses'; import { ServiceItem, Slide } from '../../responses';
interface Tag { interface Tag {
text: string; text: string;
@ -13,10 +13,13 @@ interface Tag {
styleUrls: ['./stage-view.component.scss', '../overlay.scss'] styleUrls: ['./stage-view.component.scss', '../overlay.scss']
}) })
export class StageViewComponent implements OnInit { export class StageViewComponent implements OnInit {
serviceItem: ServiceItem = null;
notes = '';
currentSlides: Slide[] = []; currentSlides: Slide[] = [];
activeSlide = 0; activeSlide = 0;
tags: Tag[] = []; tags: Tag[] = [];
time = new Date(); time = new Date();
constructor(private openlpService: OpenLPService) { constructor(private openlpService: OpenLPService) {
setInterval(() => this.time = new Date(), 1000); setInterval(() => this.time = new Date(), 1000);
} }
@ -27,7 +30,15 @@ export class StageViewComponent implements OnInit {
} }
updateCurrentSlides(): void { updateCurrentSlides(): void {
this.openlpService.getItemSlides().subscribe(slides => this.setNewSlides(slides)); this.openlpService.getServiceItem().subscribe(serviceItem => {
if (serviceItem instanceof Array) {
this.setNewSlides(serviceItem);
}
else {
this.setNewSlides(serviceItem.slides);
this.setNotes(serviceItem.notes);
}
});
} }
get nextSlides(): Slide[] { get nextSlides(): Slide[] {
@ -43,6 +54,10 @@ export class StageViewComponent implements OnInit {
this.updateTags(); this.updateTags();
} }
setNotes(notes: string): void {
this.notes = notes;
}
/** /**
* This method updates the tags from the current slides. * This method updates the tags from the current slides.
* *

View File

@ -28,7 +28,10 @@ const deserialize = (json, cls) => {
}; };
const httpOptions = { const httpOptions = {
headers: new HttpHeaders({'Content-Type': 'application/json'}) headers: new HttpHeaders({
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
})
}; };
@ -98,10 +101,14 @@ export class OpenLPService {
return this.http.post(`${this.apiURL}/service/progress`, {'action': 'previous'}, httpOptions); return this.http.post(`${this.apiURL}/service/progress`, {'action': 'previous'}, httpOptions);
} }
getItemSlides(): Observable<Slide[]> { getServiceItem(): Observable<any> {
return this.http.get<Slide[]>(`${this.apiURL}/controller/live-item`, httpOptions); return this.http.get<Slide[]>(`${this.apiURL}/controller/live-item`, httpOptions);
} }
getNotes(): Observable<any> {
return this.http.get(`${this.apiURL}/controller/notes`, httpOptions);
}
setSlide(id: any): Observable<any> { setSlide(id: any): Observable<any> {
return this.http.post(`${this.apiURL}/controller/show`, {'id': id}, httpOptions); return this.http.post(`${this.apiURL}/controller/show`, {'id': id}, httpOptions);
} }

View File

@ -33,6 +33,7 @@ export interface ServiceItem {
selected: boolean; selected: boolean;
title: string; title: string;
is_valid: boolean; is_valid: boolean;
slides: object[];
} }
export interface Theme { export interface Theme {