Merge branch 'component-refactor' into 'master'

Service + Slide Component refactor

See merge request openlp/web-remote!39
This commit is contained in:
Tim Bentley 2021-09-06 07:11:20 +00:00
commit 62dfb688e7
18 changed files with 230 additions and 109 deletions

View File

@ -38,6 +38,10 @@ 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';
import { ThemesComponent } from './components/themes/themes.component'; import { ThemesComponent } from './components/themes/themes.component';
import { SlideListComponent } from './components/slides/slide-list/slide-list.component';
import { SlideItemComponent } from './components/slides/slide-item/slide-item.component';
import { ServiceItemComponent } from './components/service/service-item/service-item.component';
import { ServiceListComponent } from './components/service/service-list/service-list.component';
@NgModule({ @NgModule({
@ -50,10 +54,14 @@ import { ThemesComponent } from './components/themes/themes.component';
ChordProPipe, ChordProPipe,
LoginComponent, LoginComponent,
ServiceComponent, ServiceComponent,
ServiceListComponent,
ServiceItemComponent,
AlertComponent, AlertComponent,
SearchComponent, SearchComponent,
SearchOptionsComponent, SearchOptionsComponent,
SlidesComponent, SlidesComponent,
SlideListComponent,
SlideItemComponent,
ThemesComponent ThemesComponent
], ],
imports: [ imports: [

View File

@ -0,0 +1,3 @@
<mat-card (click)="onItemSelected(item)" class="service-item no-select" [class.selected]="selected">
<mat-icon>{{ getIcon(item) }}</mat-icon> {{ item.title }}
</mat-card>

View File

@ -0,0 +1,40 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { ServiceItem } from '../../../responses';
@Component({
selector: 'openlp-service-item',
templateUrl: './service-item.component.html',
styleUrls: ['./service-item.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ServiceItemComponent {
@Input() item: ServiceItem;
@Input() selected = false;
@Output() select = new EventEmitter<ServiceItem>();
onItemSelected(item: ServiceItem) {
this.select.emit(item);
}
getIcon(item: ServiceItem): string {
if (!item.is_valid) {
return 'delete';
} else if (item.plugin === 'songs') {
return 'queue_music';
} else if (item.plugin === 'images') {
return 'image';
} else if (item.plugin === 'bibles') {
return 'book';
} else if (item.plugin === 'media') {
return 'movie';
} else if (item.plugin === 'custom') {
return 'description';
} else if (item.plugin === 'presentations') {
return 'slideshow';
}
return 'crop_square';
}
}

View File

@ -0,0 +1,7 @@
<openlp-service-item
*ngFor="let item of items"
[item]="item"
[selected]="item.selected"
(select)="onItemSelected($event)"
[tabindex]="item.id"
></openlp-service-item>

View File

@ -0,0 +1,41 @@
import { Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core';
import { Subscription } from 'rxjs';
import { OpenLPService } from '../../../openlp.service';
import { ServiceItem } from '../../../responses';
@Component({
selector: 'openlp-service-list',
templateUrl: './service-list.component.html',
styleUrls: ['./service-list.component.scss'],
})
export class ServiceListComponent implements OnInit, OnDestroy {
items: ServiceItem[] = [];
_subscription: Subscription;
@Output() itemSelected = new EventEmitter<ServiceItem>();
ngOnInit() {
this.fetchServiceItems();
}
onItemSelected(item: ServiceItem) {
this.itemSelected.emit(item);
}
fetchServiceItems() {
this.openlpService.getServiceItems().subscribe(items => this.items = items);
}
constructor(private openlpService: OpenLPService) {
this._subscription = openlpService.stateChanged$.subscribe(state => {
this.fetchServiceItems();
});
}
ngOnDestroy() {
this._subscription.unsubscribe();
}
}

View File

@ -1,3 +1 @@
<mat-card *ngFor="let item of items; let counter = index;" (click)="onItemSelected(item)" [tabindex]="item.id" class="service-item no-select"> <openlp-service-list (itemSelected)="this.onItemSelected($event)"></openlp-service-list>
<mat-icon>{{ getIcon(item) }}</mat-icon> {{ item.title }}
</mat-card>

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core'; import { Component } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { OpenLPService } from '../../openlp.service'; import { OpenLPService } from '../../openlp.service';
@ -9,50 +9,18 @@ import { ServiceItem } from '../../responses';
selector: 'openlp-service', selector: 'openlp-service',
templateUrl: './service.component.html', templateUrl: './service.component.html',
styleUrls: ['./service.component.scss'], styleUrls: ['./service.component.scss'],
providers: [OpenLPService]
}) })
export class ServiceComponent implements OnInit { export class ServiceComponent {
items: ServiceItem[] = []; onItemSelected(item: ServiceItem) {
ngOnInit() {
this.getServiceItems();
}
onItemSelected(item) {
if (item.is_valid) { if (item.is_valid) {
this.openlpService.setServiceItem(item.id).subscribe(); this.openlpService.setServiceItem(item.id).subscribe();
this.router.navigate(['slides']); this.router.navigate(['slides']);
} }
} }
getServiceItems() { constructor(protected pageTitleService: PageTitleService, protected openlpService: OpenLPService,
this.openlpService.getServiceItems().subscribe(items => this.items = items); protected router: Router) {
}
constructor(private pageTitleService: PageTitleService, private openlpService: OpenLPService,
private router: Router) {
pageTitleService.changePageTitle('Service'); pageTitleService.changePageTitle('Service');
openlpService.stateChanged$.subscribe(item => this.getServiceItems());
} }
getIcon(item: ServiceItem): string {
if (!item.is_valid) {
return 'delete';
} else if (item.plugin === 'songs') {
return 'queue_music';
} else if (item.plugin === 'images') {
return 'image';
} else if (item.plugin === 'bibles') {
return 'book';
} else if (item.plugin === 'media') {
return 'movie';
} else if (item.plugin === 'custom') {
return 'description';
} else if (item.plugin === 'presentations') {
return 'slideshow';
}
return 'crop_square';
}
} }

View File

@ -0,0 +1,13 @@
<mat-card class="slide no-select" mat-list-item (click)="onSlideSelected(slide)" [class.selected]="selected">
<div class="verse-tag">{{ slide?.tag }}</div>
<div *ngIf="slide?.img; else onlySlideText" class="verse-img-container">
<img src="{{ slide?.img }}" />
<div class="img-verse-text">
{{ slide?.text }}
</div>
</div>
<ng-template #onlySlideText>
<div class="verse-text">{{ slide?.text }}</div>
</ng-template>
</mat-card>

View File

@ -0,0 +1,34 @@
mat-card {
cursor: pointer;
}
.selected {
background-color: rgb(235, 235, 235);
font-weight: 700;
}
.verse-tag {
float: left;
}
.verse-text {
margin-left: 2.5rem;
white-space: pre-wrap;
}
/* Styles for displaying thumbnails */
.verse-img-container {
/* CSS for formatting DIV containing the image */
margin-left: 2.5rem;
display: inline-block;
}
.verse-img-container img {
/* Roughly basing these values off of the current thumbnail size */
/* Images sent from OpenLP should be larger and should be sized based on viewer screen size */
max-height: 75%;
min-height: 88px;
}
.img-verse-text {
font-size: 1.1rem;
white-space: pre-wrap;
}

View File

@ -0,0 +1,20 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { Slide } from '../../../responses';
@Component({
selector: 'openlp-slide-item',
templateUrl: './slide-item.component.html',
styleUrls: ['./slide-item.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SlideItemComponent {
@Input() slide: Slide;
@Input() selected = false;
@Output() select = new EventEmitter<Slide>();
onSlideSelected(slide: Slide) {
this.select.emit(slide);
}
}

View File

@ -0,0 +1 @@
<openlp-slide-item *ngFor="let slide of slides; let index = index" [slide]="slide" [tabindex]="counter" [selected]="slide.selected" (select)="onSlideSelected($event, index)"></openlp-slide-item>

View File

@ -0,0 +1,50 @@
import { Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core';
import { Subscription } from 'rxjs';
import { Slide } from '../../../responses';
import { OpenLPService } from '../../../openlp.service';
@Component({
selector: 'openlp-slide-list',
templateUrl: './slide-list.component.html',
styleUrls: ['./slide-list.component.scss'],
})
export class SlideListComponent implements OnInit, OnDestroy {
slides: Slide[] = null;
@Output() slideSelected = new EventEmitter<SlideListItem>();
_subscription: Subscription;
constructor(private openlpService: OpenLPService) {
this._subscription = openlpService.stateChanged$.subscribe(item => this.fetchSlides());
}
ngOnInit() {
this.fetchSlides();
}
ngOnDestroy() {
this._subscription.unsubscribe();
}
onSlideSelected(slide: Slide, index: number) {
this.slideSelected.emit({slide, index});
}
fetchSlides() {
this.openlpService.getServiceItem().subscribe(serviceItem => {
if (serviceItem instanceof Array) {
this.slides = serviceItem;
}
else {
this.slides = serviceItem.slides;
}
});
}
}
export interface SlideListItem {
slide: Slide;
index: number;
}

View File

@ -1,12 +1 @@
<mat-card class="no-select" mat-list-item *ngFor="let slide of slides; let counter = index;" (click)="onSlideSelected(counter)" [class.selected]="slide.selected"> <openlp-slide-list (slideSelected)="onSlideSelected($event)"></openlp-slide-list>
<div class="verse-tag">{{ slide.tag }}</div>
<div *ngIf="slide.img; else onlySlideText" class="verse-img-container">
<img src="{{ slide.img }}" />
<div class="img-verse-text">
{{ slide.text }}
</div>
</div>
<ng-template #onlySlideText>
<div class="verse-text">{{ slide.text }}</div>
</ng-template>
</mat-card>

View File

@ -1,33 +0,0 @@
mat-card {
cursor: pointer;
}
.selected {
background-color: rgb(235, 235, 235);
font-weight: 700;
}
.verse-tag {
float: left;
}
.verse-text {
margin-left: 2.5rem;
white-space: pre-wrap;
}
/* Styles for displaying thumbnails */
.verse-img-container {
/* CSS for formatting DIV containing the image */
margin-left: 2.5rem;
display: inline-block;
}
.verse-img-container img {
/* Roughly basing these values off of the current thumbnail size */
/* Images sent from OpenLP should be larger and should be sized based on viewer screen size */
max-height: 75%;
min-height: 88px;
}
.img-verse-text {
font-size: 1.1rem;
white-space: pre-wrap;
}

View File

@ -1,39 +1,21 @@
import { Component, OnInit } from '@angular/core'; import { Component } from '@angular/core';
import { OpenLPService } from '../../openlp.service'; import { OpenLPService } from '../../openlp.service';
import { PageTitleService } from '../../page-title.service'; import { PageTitleService } from '../../page-title.service';
import { SlideListItem } from './slide-list/slide-list.component';
@Component({ @Component({
selector: 'openlp-slides', selector: 'openlp-slides',
templateUrl: './slides.component.html', templateUrl: './slides.component.html',
styleUrls: ['./slides.component.scss'], styleUrls: ['./slides.component.scss'],
providers: [OpenLPService]
}) })
export class SlidesComponent implements OnInit { export class SlidesComponent {
slides = null; constructor(protected pageTitleService: PageTitleService, protected openlpService: OpenLPService) {
constructor(private pageTitleService: PageTitleService, private openlpService: OpenLPService) {
pageTitleService.changePageTitle('Slides'); pageTitleService.changePageTitle('Slides');
openlpService.stateChanged$.subscribe(item => this.getSlides());
} }
ngOnInit() { onSlideSelected(item: SlideListItem) {
this.getSlides(); this.openlpService.setSlide(item.index).subscribe();
}
onSlideSelected(id) {
this.openlpService.setSlide(id).subscribe();
}
getSlides() {
this.openlpService.getServiceItem().subscribe(serviceItem => {
if (serviceItem instanceof Array) {
this.slides = serviceItem;
}
else {
this.slides = serviceItem.slides;
}
});
} }
} }