From 2d10b7a36371e7f892d5efd0e94659ae8948525c Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Tue, 21 Jul 2020 16:26:34 -0700 Subject: [PATCH] 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 --- src/app/app.module.ts | 2 + src/app/components/overlay.scss | 101 ++++++++++-------- src/app/components/slides/slides.component.ts | 9 +- src/app/components/stage-view/nl2br.pipe.ts | 17 +++ .../stage-view/stage-view.component.html | 9 +- .../stage-view/stage-view.component.ts | 19 +++- src/app/openlp.service.ts | 11 +- src/app/responses.ts | 1 + 8 files changed, 118 insertions(+), 51 deletions(-) create mode 100644 src/app/components/stage-view/nl2br.pipe.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 1eaaa52..1355fe1 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -28,6 +28,7 @@ import { SlidesComponent } from './components/slides/slides.component'; import { FormsModule } from '@angular/forms'; import { ChordViewComponent } from './components/chord-view/chord-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 { ChordProPipe } from './components/chord-view/chordpro.pipe'; import { LoginComponent } from './components/login/login.component'; @@ -39,6 +40,7 @@ import { ThemesComponent } from './components/themes/themes.component'; AppComponent, ChordViewComponent, StageViewComponent, + Nl2BrPipe, MainViewComponent, ChordProPipe, LoginComponent, diff --git a/src/app/components/overlay.scss b/src/app/components/overlay.scss index 2db0709..6270d80 100644 --- a/src/app/components/overlay.scss +++ b/src/app/components/overlay.scss @@ -1,64 +1,79 @@ .overlay { - background: black; - width: 100%; - height: 100%; - position: fixed; - left: 0; - top: 0; - z-index: 1; - overflow: hidden; - color: white; - display: flex; - flex-direction: row; - justify-content: space-between; + background: black; + width: 100%; + height: 100%; + position: fixed; + left: 0; + top: 0; + z-index: 1; + overflow: hidden; + color: white; + display: flex; + flex-direction: row; + justify-content: space-between; } .sidebar { - margin: 1rem; - display: flex; - flex-direction: column; - justify-content: space-between; + margin: 1rem; + display: flex; + flex-direction: column; + justify-content: space-between; + width: 30%; } .time { - font-size: 2rem; - color: gray; + font-size: 3rem; + 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 { - margin-top: 1rem; - margin-bottom: 1rem; - display: flex; - flex-direction: row; - justify-content: flex-start; - color: gray; - font-size: 4rem; - span { - margin-left: 1rem; - &.active { - color: white; - } + margin-top: 1rem; + margin-bottom: 1rem; + display: flex; + flex-direction: row; + justify-content: flex-start; + color: green; + font-size: 4rem; + span { + margin-left: 1rem; + &.active { + color: lightgreen; + font-weight: bold; } + } } .slide { - font-size: 3rem; - white-space: pre-line; - margin: 0; - &.first { - margin-top: 1rem; - } + font-size: 3rem; + white-space: pre-line; + margin: 0; + &.first { + margin-top: 1rem; + } } .container { - margin-left: 1rem; + margin-left: 1rem; } .nextSlides { + font-size: 2rem; + margin-top: 1rem; + color: grey; + .slide { font-size: 2rem; - margin-top: 1rem; - color: gray; - .slide { - font-size: 2rem; - } -} \ No newline at end of file + } +} diff --git a/src/app/components/slides/slides.component.ts b/src/app/components/slides/slides.component.ts index d205c95..e539423 100644 --- a/src/app/components/slides/slides.component.ts +++ b/src/app/components/slides/slides.component.ts @@ -27,6 +27,13 @@ export class SlidesComponent implements OnInit { } 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; + } + }); } } diff --git a/src/app/components/stage-view/nl2br.pipe.ts b/src/app/components/stage-view/nl2br.pipe.ts new file mode 100644 index 0000000..908a199 --- /dev/null +++ b/src/app/components/stage-view/nl2br.pipe.ts @@ -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, '
')); + } +} diff --git a/src/app/components/stage-view/stage-view.component.html b/src/app/components/stage-view/stage-view.component.html index 548466a..ee90606 100644 --- a/src/app/components/stage-view/stage-view.component.html +++ b/src/app/components/stage-view/stage-view.component.html @@ -15,7 +15,10 @@ - \ No newline at end of file + diff --git a/src/app/components/stage-view/stage-view.component.ts b/src/app/components/stage-view/stage-view.component.ts index 2eca06d..395289a 100644 --- a/src/app/components/stage-view/stage-view.component.ts +++ b/src/app/components/stage-view/stage-view.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { OpenLPService } from '../../openlp.service'; -import { Slide } from '../../responses'; +import { ServiceItem, Slide } from '../../responses'; interface Tag { text: string; @@ -13,10 +13,13 @@ interface Tag { styleUrls: ['./stage-view.component.scss', '../overlay.scss'] }) export class StageViewComponent implements OnInit { + serviceItem: ServiceItem = null; + notes = ''; currentSlides: Slide[] = []; activeSlide = 0; tags: Tag[] = []; time = new Date(); + constructor(private openlpService: OpenLPService) { setInterval(() => this.time = new Date(), 1000); } @@ -27,7 +30,15 @@ export class StageViewComponent implements OnInit { } 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[] { @@ -43,6 +54,10 @@ export class StageViewComponent implements OnInit { this.updateTags(); } + setNotes(notes: string): void { + this.notes = notes; + } + /** * This method updates the tags from the current slides. * diff --git a/src/app/openlp.service.ts b/src/app/openlp.service.ts index 7bbe660..dc40a93 100644 --- a/src/app/openlp.service.ts +++ b/src/app/openlp.service.ts @@ -28,7 +28,10 @@ const deserialize = (json, cls) => { }; 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); } - getItemSlides(): Observable { + getServiceItem(): Observable { return this.http.get(`${this.apiURL}/controller/live-item`, httpOptions); } + getNotes(): Observable { + return this.http.get(`${this.apiURL}/controller/notes`, httpOptions); + } + setSlide(id: any): Observable { return this.http.post(`${this.apiURL}/controller/show`, {'id': id}, httpOptions); } diff --git a/src/app/responses.ts b/src/app/responses.ts index 1dc46ff..5e11e93 100644 --- a/src/app/responses.ts +++ b/src/app/responses.ts @@ -33,6 +33,7 @@ export interface ServiceItem { selected: boolean; title: string; is_valid: boolean; + slides: object[]; } export interface Theme {