adding presentation background

This commit is contained in:
2022-08-14 22:11:54 +02:00
parent a02e740c0f
commit e9846b29e5
41 changed files with 212 additions and 104 deletions

View File

@@ -5,7 +5,7 @@
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
background: #000c; background: #000e;
padding: 50px; padding: 50px;
box-sizing: border-box; box-sizing: border-box;
box-shadow: 0px 0px 26px 10px #000; box-shadow: 0px 0px 26px 10px #000;

View File

@@ -1,7 +1,17 @@
<div class="fullscreen background"></div>
<div *ngIf="song && showType" [style.font-size.px]="zoom" class="fullscreen background"> <div *ngIf="song && showType" [style.font-size.px]="zoom" class="fullscreen background">
<div class="bg-blue fullscreen bg-image" [class.visible]="presentationBackground==='blue'"></div>
<div class="bg-green fullscreen bg-image" [class.visible]="presentationBackground==='green'"></div>
<div class="bg-leder fullscreen bg-image" [class.visible]="presentationBackground==='leder'"></div>
<div class="bg-praise fullscreen bg-image" [class.visible]="presentationBackground==='praise'"></div>
<div class="bg-bible fullscreen bg-image" [class.visible]="presentationBackground==='bible'"></div>
<div <div
[@songSwitch]="songId" [@songSwitch]="songId"
[class.blur]="songId === 'title'" [class.blur]="songId === 'title'"
[class.no-logo]="presentationBackground!=='none'"
[class.hide]="songId !== 'title' && songId !== 'empty'" [class.hide]="songId !== 'title' && songId !== 'empty'"
class="start fullscreen logo" class="start fullscreen logo"
> >

View File

@@ -21,7 +21,54 @@
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
transition: 300ms all ease-in-out; transition: 30ms all ease-in-out;
}
.bg-image {
z-index: 0;
opacity: 0;
background-size: cover;
transition: 5000ms opacity ease-in-out;
}
.bg-blue {
background-image: url("/assets/bg-dark-blue.jpg");
filter: blur(10px);
&.visible {
opacity: 0.5;
}
}
.bg-green {
background-image: url("/assets/bg-dark-green.jpg");
filter: blur(5px);
&.visible {
opacity: 0.9;
}
}
.bg-leder {
background-image: url("/assets/bg-leder.jpg");
filter: blur(5px);
&.visible {
opacity: 0.4;
}
}
.bg-praise {
background-image: url("/assets/bg-praise.jpg");
filter: blur(8px);
&.visible {
opacity: 0.2;
}
}
.bg-bible {
background-image: url("/assets/bg-bible.jpg");
filter: blur(8px);
&.visible {
opacity: 0.2;
}
} }
.start { .start {
@@ -56,4 +103,7 @@
filter: blur(30px); filter: blur(30px);
opacity: 0.1; opacity: 0.1;
transform: scale(0.8) translateY(-10%); transform: scale(0.8) translateY(-10%);
&.no-logo {
opacity: 0;
}
} }

View File

@@ -1,5 +1,5 @@
import {Component, OnInit} from '@angular/core'; import {Component, OnInit} from '@angular/core';
import {distinctUntilChanged, filter, map, switchMap, tap} from 'rxjs/operators'; import {debounceTime, distinctUntilChanged, filter, map, switchMap, tap} from 'rxjs/operators';
import {ShowService} from '../../shows/services/show.service'; import {ShowService} from '../../shows/services/show.service';
import {SongService} from '../../songs/services/song.service'; import {SongService} from '../../songs/services/song.service';
import {Song} from '../../songs/services/song'; import {Song} from '../../songs/services/song';
@@ -9,7 +9,7 @@ import {Observable} from 'rxjs';
import {ConfigService} from '../../../services/config.service'; import {ConfigService} from '../../../services/config.service';
import {songSwitch} from '../../../widget-modules/components/song-text/animation'; import {songSwitch} from '../../../widget-modules/components/song-text/animation';
import {TextRenderingService} from '../../songs/services/text-rendering.service'; import {TextRenderingService} from '../../songs/services/text-rendering.service';
import {Show} from '../../shows/services/show'; import {PresentationBackground, Show} from '../../shows/services/show';
import {GlobalSettings} from '../../../services/global-settings'; import {GlobalSettings} from '../../../services/global-settings';
import {ShowSongService} from '../../shows/services/show-song.service'; import {ShowSongService} from '../../shows/services/show-song.service';
@@ -28,6 +28,7 @@ export class MonitorComponent implements OnInit {
public showType: string | null = null; public showType: string | null = null;
public date: Date | null = null; public date: Date | null = null;
public config$: Observable<Config | null>; public config$: Observable<Config | null>;
public presentationBackground: PresentationBackground = 'none';
public constructor( public constructor(
private showService: ShowService, private showService: ShowService,
@@ -43,6 +44,7 @@ export class MonitorComponent implements OnInit {
public ngOnInit(): void { public ngOnInit(): void {
this.globalSettingsService.get$ this.globalSettingsService.get$
.pipe( .pipe(
debounceTime(100),
filter(_ => !!_), filter(_ => !!_),
map(_ => _ as GlobalSettings), map(_ => _ as GlobalSettings),
map(_ => _.currentShow), map(_ => _.currentShow),
@@ -53,16 +55,15 @@ export class MonitorComponent implements OnInit {
switchMap(_ => this.showService.read$(_)), switchMap(_ => this.showService.read$(_)),
filter(_ => !!_), filter(_ => !!_),
map(_ => _ as Show), map(_ => _ as Show),
tap<Show>(_ => (this.showType = _.showType)),
tap<Show>(_ => (this.date = _.date.toDate())),
tap<Show>(_ => { tap<Show>(_ => {
this.showType = _.showType;
this.date = _.date.toDate();
this.index = _.presentationSection;
this.presentationBackground = _.presentationBackground;
this.zoom = _.presentationZoom ?? 30;
if (this.songId !== _.presentationSongId) this.songId = 'empty'; if (this.songId !== _.presentationSongId) this.songId = 'empty';
setTimeout(() => (this.songId = _.presentationSongId), 300); setTimeout(() => (this.songId = _.presentationSongId), 300);
}), }),
tap<Show>(_ => (this.index = _.presentationSection)),
tap<Show>(_ => (this.zoom = _.presentationZoom ?? 30))
)
.pipe(
switchMap((_: Show) => this.showSongService.read$(_.id, _.presentationSongId)), switchMap((_: Show) => this.showSongService.read$(_.id, _.presentationSongId)),
filter(_ => !!_), filter(_ => !!_),
map(_ => _ as Song) map(_ => _ as Song)

View File

@@ -15,7 +15,8 @@
</mat-form-field> </mat-form-field>
<ng-container *ngIf="!progress"> <ng-container *ngIf="!progress">
<div *ngIf="show" class="song-parts padding-bottom"> <div class="song">
<div *ngIf="show" class="song-parts">
<div <div
(click)="onSectionClick('title', -1)" (click)="onSectionClick('title', -1)"
[class.active]="show.presentationSongId === 'title'" [class.active]="show.presentationSongId === 'title'"
@@ -31,6 +32,7 @@
<div class="head">Leer</div> <div class="head">Leer</div>
</div> </div>
</div> </div>
</div>
<div *ngFor="let song of presentationSongs; trackBy: trackBy" @fade class="song"> <div *ngFor="let song of presentationSongs; trackBy: trackBy" @fade class="song">
<div *ngIf="show" <div *ngIf="show"
@@ -60,9 +62,26 @@
</div> </div>
<div *ngIf="show" class="div-bottom"> <div *ngIf="show" class="div-bottom">
<a routerLink="/presentation/monitor" target="_blank">
<button routerLink="/presentation/monitor" mat-button>
<fa-icon [icon]="faDesktop"></fa-icon> <fa-icon [icon]="faDesktop"></fa-icon>
</a> Präsentation starten
</button>
<mat-form-field appearance="outline">
<mat-label>Hintergrund</mat-label>
<mat-select
[ngModel]="show.presentationBackground"
(ngModelChange)="onBackground($event)">
<mat-option value="none">kein Hintergrund</mat-option>
<mat-option value="blue">Sternenhimmel</mat-option>
<mat-option value="green">Blätter</mat-option>
<mat-option value="leder">Leder</mat-option>
<mat-option value="praise">Lobpreis</mat-option>
<mat-option value="bible">Bibel</mat-option>
</mat-select>
</mat-form-field>
<mat-slider <mat-slider
(ngModelChange)="onZoom($event)" (ngModelChange)="onZoom($event)"
@@ -72,8 +91,10 @@
[step]="2" [step]="2"
[thumbLabel]="true" [thumbLabel]="true"
color="primary" color="primary"
class="zoom-slider"
> >
</mat-slider> </mat-slider>
</div> </div>
<app-add-song <app-add-song

View File

@@ -1,12 +1,20 @@
@import "../../../../styles/shadow"; @import "../../../../styles/shadow";
.song { .song {
background: #fff5; background: #fff;
width: 100%; width: 100%;
padding: 10px; padding: 10px;
border-radius: 8px; border-radius: 8px;
margin-bottom: 10px; margin-bottom: 10px;
box-sizing: border-box; box-sizing: border-box;
@media screen and (max-width: 860px) {
width: 100vw;
padding: 10px 20px;
border-radius: 0;
box-sizing: border-box;
margin: 0 -20px 10px;
}
} }
.title { .title {
@@ -35,19 +43,23 @@
overflow: hidden; overflow: hidden;
transition: 300ms all ease-in-out; transition: 300ms all ease-in-out;
cursor: pointer; cursor: pointer;
// .card-1; outline: 0.5px solid #f4f4f4;
&:hover { &:hover {
.card-1; .card-1;
outline: 0px solid transparent;
} }
&.active { &.active {
.card-2; .card-2;
outline: 0px solid transparent;
.head { .head {
background: #4286f4; background: #4286f4;
color: white; color: white;
border-bottom: 0.5px solid #4286f4; }
.fragment {
} }
} }
} }
@@ -55,7 +67,6 @@
.head { .head {
transition: 300ms all ease-in-out; transition: 300ms all ease-in-out;
background: #f4f4f4; background: #f4f4f4;
border-bottom: 0.5px solid #ddd;
padding: 10px; padding: 10px;
font-weight: bold; font-weight: bold;
} }
@@ -66,9 +77,21 @@
.div-bottom { .div-bottom {
display: grid; display: grid;
grid-template-columns: 60px auto; gap: 20px;
grid-template-columns: min-content min-content auto;
@media screen and (max-width: 860px) {
gap: 0;
grid-template-columns: auto;
}
::ng-deep.mat-form-field-wrapper {
margin: 0;
padding: 0;
}
} }
.padding-bottom { .padding-bottom {
padding-bottom: 20px; padding-bottom: 20px;
} }
@@ -77,6 +100,7 @@ a {
font-size: 30px; font-size: 30px;
padding: 10px; padding: 10px;
transition: all 300ms ease-in-out; transition: all 300ms ease-in-out;
&:hover { &:hover {
color: #4286f4; color: #4286f4;
} }

View File

@@ -1,15 +1,15 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {combineLatest, Observable} from 'rxjs'; import {combineLatest, Observable} from 'rxjs';
import {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 {Song} from '../../songs/services/song'; import {Song} from '../../songs/services/song';
import {faDesktop} from '@fortawesome/free-solid-svg-icons/faDesktop'; import {faDesktop} 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 {FormControl} from '@angular/forms'; import {FormControl} from '@angular/forms';
import {distinctUntilChanged, filter, map} from 'rxjs/operators'; import {debounceTime, distinctUntilChanged, filter, map} from 'rxjs/operators';
import {fade} from '../../../animations'; import {fade} from '../../../animations';
import {delay} from '../../../services/delay'; import {delay} from '../../../services/delay';
import {TextRenderingService} from '../../songs/services/text-rendering.service'; import {TextRenderingService} from '../../songs/services/text-rendering.service';
@@ -72,12 +72,15 @@ export class RemoteComponent {
this.progress = true; this.progress = true;
if (updateShow) { if (updateShow) {
await this.showService.update$(change, {presentationSongId: 'empty'}); await this.showService.update$(change, {presentationSongId: 'empty'});
await delay(1200); await delay(200);
await this.globalSettingsService.set({currentShow: change}); await this.globalSettingsService.set({currentShow: change});
await this.showService.update$(change, {presentationSongId: 'title'}); await this.showService.update$(change, {presentationSongId: 'title'});
} }
this.currentShowId = change; this.currentShowId = change;
this.showService.read$(change).subscribe(show => { this.showService
.read$(change)
.pipe(debounceTime(100))
.subscribe(show => {
this.show = show; this.show = show;
}); });
@@ -106,7 +109,11 @@ export class RemoteComponent {
}); });
} }
public async onZoom(zoom: number): Promise<void> { public async onZoom(presentationZoom: number): Promise<void> {
if (this.currentShowId != null) await this.showService.update$(this.currentShowId, {presentationZoom: zoom}); if (this.currentShowId != null) await this.showService.update$(this.currentShowId, {presentationZoom});
}
public async onBackground(presentationBackground: PresentationBackground): Promise<void> {
if (this.currentShowId != null) await this.showService.update$(this.currentShowId, {presentationBackground});
} }
} }

View File

@@ -5,7 +5,7 @@ import {Show} from '../services/show';
import {ShowService} from '../services/show.service'; import {ShowService} from '../services/show.service';
import {FormControl, FormGroup, Validators} from '@angular/forms'; import {FormControl, FormGroup, Validators} from '@angular/forms';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import {faSave} from '@fortawesome/free-solid-svg-icons/faSave'; import {faSave} from '@fortawesome/free-solid-svg-icons';
@Component({ @Component({
selector: 'app-new', selector: 'app-new',
@@ -36,7 +36,7 @@ export class NewComponent implements OnInit {
return; return;
} }
const id = await this.showService.new$(this.form.value); const id = await this.showService.new$(this.form.value as Partial<Show>);
await this.router.navigateByUrl(`/shows/${id ?? ''}`); await this.router.navigateByUrl(`/shows/${id ?? ''}`);
} }
} }

View File

@@ -1,6 +1,8 @@
import firebase from 'firebase/compat/app'; import firebase from 'firebase/compat/app';
import Timestamp = firebase.firestore.Timestamp; import Timestamp = firebase.firestore.Timestamp;
export type PresentationBackground = 'none' | 'blue' | 'green' | 'leder' | 'praise';
export interface Show { export interface Show {
id: string; id: string;
showType: string; showType: string;
@@ -15,4 +17,5 @@ export interface Show {
presentationSongId: string; presentationSongId: string;
presentationSection: number; presentationSection: number;
presentationZoom: number; presentationZoom: number;
presentationBackground: PresentationBackground;
} }

View File

@@ -8,7 +8,7 @@
<i>{{show.public ? 'öffentliche' : 'geschlossene'}} Veranstaltung von <i>{{show.public ? 'öffentliche' : 'geschlossene'}} Veranstaltung von
<app-user-name [userId]="show.owner"></app-user-name> <app-user-name [userId]="show.owner"></app-user-name>
</i> </i>
<p *ngIf="!show.published"> <p >
<mat-checkbox [(ngModel)]="showText">Text anzeigen</mat-checkbox> <mat-checkbox [(ngModel)]="showText">Text anzeigen</mat-checkbox>
</p> </p>
<div *ngIf="showSongs" class="song-list" cdkDropList [cdkDropListDisabled]="show.published" <div *ngIf="showSongs" class="song-list" cdkDropList [cdkDropListDisabled]="show.published"

View File

@@ -9,13 +9,7 @@ import {Song} from '../../songs/services/song';
import {ShowSongService} from '../services/show-song.service'; import {ShowSongService} from '../services/show-song.service';
import {ShowSong} from '../services/show-song'; import {ShowSong} from '../services/show-song';
import {DocxService} from '../services/docx.service'; import {DocxService} from '../services/docx.service';
import {faBox} from '@fortawesome/free-solid-svg-icons/faBox'; import {faBox, faBoxOpen, faExternalLinkAlt, faFileDownload, faLock, faUser, faUsers} from '@fortawesome/free-solid-svg-icons';
import {faBoxOpen} from '@fortawesome/free-solid-svg-icons/faBoxOpen';
import {faExternalLinkAlt} from '@fortawesome/free-solid-svg-icons/faExternalLinkAlt';
import {faLock} from '@fortawesome/free-solid-svg-icons/faLock';
import {faFileDownload} from '@fortawesome/free-solid-svg-icons/faFileDownload';
import {faUser} from '@fortawesome/free-solid-svg-icons/faUser';
import {faUsers} from '@fortawesome/free-solid-svg-icons/faUsers';
import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop'; import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop';
@Component({ @Component({

View File

@@ -1,5 +1,5 @@
<div *ngIf="iSong && iSong && show"> <div *ngIf="iSong && iSong && show">
<div @fade *ngIf="show.published" class="title published">{{ iSong.title }}</div> <div @fade *ngIf="show.published" class="title published">{{ iSong.key }} - {{ iSong.title }}</div>
<div @fade *ngIf="!show.published" class="song"> <div @fade *ngIf="!show.published" class="song">
<span class="title">{{ iSong.title }}</span> <span class="title">{{ iSong.title }}</span>
@@ -31,7 +31,7 @@
<app-song-text <app-song-text
(chordModeChanged)="onChordModeChanged($event)" (chordModeChanged)="onChordModeChanged($event)"
*ngIf="!edit && (showText || show.published)" *ngIf="!edit && (showText )"
[chordMode]="iSong.chordMode" [chordMode]="iSong.chordMode"
[showSwitch]="!show.published" [showSwitch]="!show.published"
[text]="iSong.text" [text]="iSong.text"

View File

@@ -1,14 +1,11 @@
import {Component, Input, OnInit} from '@angular/core'; import {Component, Input, OnInit} from '@angular/core';
import {faTrash} from '@fortawesome/free-solid-svg-icons/faTrash';
import {ShowSongService} from '../../services/show-song.service'; import {ShowSongService} from '../../services/show-song.service';
import {ShowSong} from '../../services/show-song'; import {ShowSong} from '../../services/show-song';
import {getScale} from '../../../songs/services/key.helper'; import {getScale} from '../../../songs/services/key.helper';
import {FormControl} from '@angular/forms'; import {FormControl} from '@angular/forms';
import {ChordMode} from '../../../../widget-modules/components/song-text/song-text.component'; import {ChordMode} from '../../../../widget-modules/components/song-text/song-text.component';
import {Show} from '../../services/show'; import {Show} from '../../services/show';
import {faPenToSquare} from '@fortawesome/free-solid-svg-icons/faPenToSquare'; import {faEraser, faPenToSquare, faSave, faTrash} from '@fortawesome/free-solid-svg-icons';
import {faSave} from '@fortawesome/free-solid-svg-icons/faSave';
import {faEraser} from '@fortawesome/free-solid-svg-icons/faEraser';
import {fade} from '../../../../animations'; import {fade} from '../../../../animations';
@Component({ @Component({

View File

@@ -8,15 +8,20 @@ import Timestamp = firebase.firestore.Timestamp;
// declare let importCCLI: any; // declare let importCCLI: any;
export type SongType = 'Praise' | 'Worship' | 'Misc';
export type SongStatus = 'draft' | 'set' | 'final';
export type SongLegalOwner = 'CCLI' | 'other';
export type SongLegalType = 'open' | 'allowed';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
}) })
export class SongService { export class SongService {
public static TYPES = ['Praise', 'Worship']; public static TYPES: SongType[] = ['Praise', 'Worship', 'Misc'];
public static STATUS = ['draft', 'set', 'final']; public static STATUS: SongStatus[] = ['draft', 'set', 'final'];
public static LEGAL_OWNER = ['CCLI', 'other']; public static LEGAL_OWNER: SongLegalOwner[] = ['CCLI', 'other'];
public static LEGAL_TYPE = ['open', 'allowed']; public static LEGAL_TYPE: SongLegalType[] = ['open', 'allowed'];
// private list: Song[]; // private list: Song[];

View File

@@ -1,4 +1,5 @@
import firebase from 'firebase/compat/app'; import firebase from 'firebase/compat/app';
import {SongLegalOwner, SongLegalType, SongStatus, SongType} from './song.service';
import Timestamp = firebase.firestore.Timestamp; import Timestamp = firebase.firestore.Timestamp;
export interface Song { export interface Song {
@@ -10,12 +11,12 @@ export interface Song {
tempo: number; tempo: number;
text: string; text: string;
title: string; title: string;
type: string; type: SongType;
flags: string; flags: string;
status: string; status: SongStatus;
legalType: string; legalType: SongLegalType;
legalOwner: string; legalOwner: SongLegalOwner;
legalOwnerId: string; legalOwnerId: string;
artist: string; artist: string;

View File

@@ -1,8 +1,6 @@
import {Component, Input} from '@angular/core'; import {Component, Input} from '@angular/core';
import {Song} from '../../services/song'; import {Song} from '../../services/song';
import {faBalanceScaleRight} from '@fortawesome/free-solid-svg-icons/faBalanceScaleRight'; import {faBalanceScaleRight, faCheck, faPencilRuler} from '@fortawesome/free-solid-svg-icons';
import {faPencilRuler} from '@fortawesome/free-solid-svg-icons/faPencilRuler';
import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck';
@Component({ @Component({
selector: 'app-list-item', selector: 'app-list-item',

View File

@@ -1,7 +1,7 @@
import {Component, Input} from '@angular/core'; import {Component, Input} from '@angular/core';
import {Observable} from 'rxjs'; import {Observable} from 'rxjs';
import {File} from '../../../../services/file'; import {File} from '../../../../services/file';
import {faTrashAlt} from '@fortawesome/free-solid-svg-icons/faTrashAlt'; import {faTrashAlt} from '@fortawesome/free-solid-svg-icons';
import {FileService} from '../../../../services/file.service'; import {FileService} from '../../../../services/file.service';
@Component({ @Component({

View File

@@ -8,9 +8,7 @@ import {first, map, switchMap} from 'rxjs/operators';
import {KEYS} from '../../../services/key.helper'; import {KEYS} from '../../../services/key.helper';
import {COMMA, ENTER} from '@angular/cdk/keycodes'; import {COMMA, ENTER} from '@angular/cdk/keycodes';
import {MatChipInputEvent} from '@angular/material/chips'; import {MatChipInputEvent} from '@angular/material/chips';
import {faTimesCircle} from '@fortawesome/free-solid-svg-icons/faTimesCircle'; import {faExternalLinkAlt, faSave, faTimesCircle} from '@fortawesome/free-solid-svg-icons';
import {faSave} from '@fortawesome/free-solid-svg-icons/faSave';
import {faExternalLinkAlt} from '@fortawesome/free-solid-svg-icons/faExternalLinkAlt';
import {MatDialog} from '@angular/material/dialog'; import {MatDialog} from '@angular/material/dialog';
import {SaveDialogComponent} from './save-dialog/save-dialog.component'; import {SaveDialogComponent} from './save-dialog/save-dialog.component';
@@ -54,8 +52,8 @@ export class EditSongComponent implements OnInit {
this.song = song; this.song = song;
if (!song) return; if (!song) return;
this.form = this.editService.createSongForm(song); this.form = this.editService.createSongForm(song);
this.form.controls.flags.valueChanges.subscribe(_ => this.onFlagsChanged(_)); this.form.controls.flags.valueChanges.subscribe(_ => this.onFlagsChanged(_ as string));
this.onFlagsChanged(this.form.controls.flags.value); this.onFlagsChanged(this.form.controls.flags.value as string);
}); });
} }

View File

@@ -1,5 +1,5 @@
import {Component, OnDestroy, OnInit} from '@angular/core'; import {Component, OnDestroy, OnInit} from '@angular/core';
import {faSave} from '@fortawesome/free-solid-svg-icons/faSave'; import {faSave} from '@fortawesome/free-solid-svg-icons';
import {FormControl, FormGroup, Validators} from '@angular/forms'; import {FormControl, FormGroup, Validators} from '@angular/forms';
import {SongService} from '../../services/song.service'; import {SongService} from '../../services/song.service';
import {Song} from '../../services/song'; import {Song} from '../../services/song';

View File

@@ -8,8 +8,7 @@ import {FileDataService} from '../services/file-data.service';
import {File} from '../services/file'; import {File} from '../services/file';
import {UserService} from '../../../services/user/user.service'; import {UserService} from '../../../services/user/user.service';
import {User} from '../../../services/user/user'; import {User} from '../../../services/user/user';
import {faEdit} from '@fortawesome/free-solid-svg-icons/faEdit'; import {faEdit, faTrash} from '@fortawesome/free-solid-svg-icons';
import {faTrash} from '@fortawesome/free-solid-svg-icons/faTrash';
@Component({ @Component({
selector: 'app-song', selector: 'app-song',

View File

@@ -3,7 +3,7 @@ import {UserService} from '../../../services/user/user.service';
import {Observable} from 'rxjs'; import {Observable} from 'rxjs';
import {User} from '../../../services/user/user'; import {User} from '../../../services/user/user';
import {ChordMode} from '../../../widget-modules/components/song-text/song-text.component'; import {ChordMode} from '../../../widget-modules/components/song-text/song-text.component';
import {faSignOutAlt} from '@fortawesome/free-solid-svg-icons/faSignOutAlt'; import {faSignOutAlt} from '@fortawesome/free-solid-svg-icons';
import {RolePipe} from './role.pipe'; import {RolePipe} from './role.pipe';
import {roles} from '../../../services/user/roles'; import {roles} from '../../../services/user/roles';

View File

@@ -2,7 +2,7 @@ import {Component, Input} from '@angular/core';
import {User} from '../../../../../services/user/user'; import {User} from '../../../../../services/user/user';
import {UserService} from '../../../../../services/user/user.service'; import {UserService} from '../../../../../services/user/user.service';
import {ROLE_TYPES} from '../../../../../services/user/roles'; import {ROLE_TYPES} from '../../../../../services/user/roles';
import {faTimes} from '@fortawesome/free-solid-svg-icons/faTimes'; import {faTimes} from '@fortawesome/free-solid-svg-icons';
@Component({ @Component({
selector: 'app-user', selector: 'app-user',

View File

@@ -2,8 +2,7 @@ import {Component, OnInit} from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms'; import {FormControl, FormGroup, Validators} from '@angular/forms';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import {UserService} from '../../../services/user/user.service'; import {UserService} from '../../../services/user/user.service';
import {faSignInAlt} from '@fortawesome/free-solid-svg-icons/faSignInAlt'; import {faSignInAlt, faUserPlus} from '@fortawesome/free-solid-svg-icons';
import {faUserPlus} from '@fortawesome/free-solid-svg-icons/faUserPlus';
@Component({ @Component({
selector: 'app-login', selector: 'app-login',

View File

@@ -1,7 +1,7 @@
import {Component, OnInit} from '@angular/core'; import {Component, OnInit} from '@angular/core';
import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms'; import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms';
import {UserService} from '../../../services/user/user.service'; import {UserService} from '../../../services/user/user.service';
import {faUserPlus} from '@fortawesome/free-solid-svg-icons/faUserPlus'; import {faUserPlus} from '@fortawesome/free-solid-svg-icons';
@Component({ @Component({
selector: 'app-new', selector: 'app-new',

View File

@@ -2,7 +2,7 @@ import {Component, OnInit} from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms'; import {FormControl, FormGroup, Validators} from '@angular/forms';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import {UserService} from '../../../services/user/user.service'; import {UserService} from '../../../services/user/user.service';
import {faWindowRestore} from '@fortawesome/free-solid-svg-icons/faWindowRestore'; import {faWindowRestore} from '@fortawesome/free-solid-svg-icons';
@Component({ @Component({
selector: 'app-password', selector: 'app-password',

View File

@@ -3,13 +3,13 @@ import {Song} from '../modules/songs/services/song';
export function filterSong(song: Song, filterValue: string): boolean { export function filterSong(song: Song, filterValue: string): boolean {
if (!filterValue) return true; if (!filterValue) return true;
const textMatch = !!song.text && normalize(song.text).indexOf(normalize(filterValue)) !== -1; const textMatch = !!song.text && normalize(song.text)?.indexOf(normalize(filterValue)) !== -1;
const titleMatch = !!song.title && normalize(song.title).indexOf(normalize(filterValue)) !== -1; const titleMatch = !!song.title && normalize(song.title)?.indexOf(normalize(filterValue)) !== -1;
const artistMatch = !!song.title && normalize(song.artist).indexOf(normalize(filterValue)) !== -1; const artistMatch = !!song.title && normalize(song.artist)?.indexOf(normalize(filterValue)) !== -1;
return textMatch || titleMatch || artistMatch; return textMatch || titleMatch || artistMatch;
} }
function normalize(input: string): string { function normalize(input: string): string {
return input.toLowerCase().replace(/[\s?!.,']/g, ''); return input?.toLowerCase().replace(/[\s?!.,']/g, '');
} }

View File

@@ -3,7 +3,7 @@
.card { .card {
margin: 20px; margin: 20px;
border-radius: 8px; border-radius: 8px;
background: #fffb; background: #fffe;
backdrop-filter: blur(12px); backdrop-filter: blur(12px);
overflow: hidden; overflow: hidden;
width: 800px; width: 800px;
@@ -11,8 +11,8 @@
@media screen and (max-width: 860px) { @media screen and (max-width: 860px) {
width: 100vw; width: 100vw;
border-radius: 0px; border-radius: 0;
background: #fffa; background: #fffe;
margin: 0; margin: 0;
} }

View File

@@ -1,5 +1,5 @@
import {Component, Input} from '@angular/core'; import {Component, Input} from '@angular/core';
import {faTimes} from '@fortawesome/free-solid-svg-icons/faTimes'; import {faTimes} from '@fortawesome/free-solid-svg-icons';
@Component({ @Component({
selector: 'app-card', selector: 'app-card',

View File

@@ -1,6 +1,5 @@
import {Component, EventEmitter, Input, Output} from '@angular/core'; import {Component, EventEmitter, Input, Output} from '@angular/core';
import {faFilter} from '@fortawesome/free-solid-svg-icons/faFilter'; import {faFilter, faPlus} from '@fortawesome/free-solid-svg-icons';
import {faPlus} from '@fortawesome/free-solid-svg-icons/faPlus';
import {fade} from '../../../animations'; import {fade} from '../../../animations';
@Component({ @Component({

View File

@@ -1,6 +1,6 @@
import {Component, Input} from '@angular/core'; import {Component, Input} from '@angular/core';
import {IconProp} from '@fortawesome/fontawesome-svg-core'; import {IconProp} from '@fortawesome/fontawesome-svg-core';
import {faCross} from '@fortawesome/free-solid-svg-icons/faCross'; import {faCross} from '@fortawesome/free-solid-svg-icons';
@Component({ @Component({
selector: 'app-menu-button', selector: 'app-menu-button',

View File

@@ -27,7 +27,7 @@
.line { .line {
opacity: 1; opacity: 1;
transition: 1000ms all ease-in-out; transition: 100ms all ease-in-out;
&.disabled { &.disabled {
opacity: 0.5; opacity: 0.5;
@@ -65,7 +65,7 @@
left: 40px; left: 40px;
right: 40px; right: 40px;
transition: 1000ms all ease-in-out; transition: 1000ms top ease-in-out;
} }
.error { .error {

View File

@@ -1,10 +1,11 @@
import {Pipe, PipeTransform} from '@angular/core'; import {Pipe, PipeTransform} from '@angular/core';
import {SongLegalOwner} from '../../../modules/songs/services/song.service';
@Pipe({ @Pipe({
name: 'legalOwner', name: 'legalOwner',
}) })
export class LegalOwnerPipe implements PipeTransform { export class LegalOwnerPipe implements PipeTransform {
public transform(legalOwnerKey: string): string { public transform(legalOwnerKey: SongLegalOwner): string {
switch (legalOwnerKey) { switch (legalOwnerKey) {
case 'CCLI': case 'CCLI':
return 'CCLI'; return 'CCLI';

View File

@@ -1,10 +1,11 @@
import {Pipe, PipeTransform} from '@angular/core'; import {Pipe, PipeTransform} from '@angular/core';
import {SongLegalType} from '../../../modules/songs/services/song.service';
@Pipe({ @Pipe({
name: 'legalType', name: 'legalType',
}) })
export class LegalTypePipe implements PipeTransform { export class LegalTypePipe implements PipeTransform {
public transform(legalTypeKey: string): string { public transform(legalTypeKey: SongLegalType): string {
switch (legalTypeKey) { switch (legalTypeKey) {
case 'open': case 'open':
return 'Klärung erforderlich '; return 'Klärung erforderlich ';

View File

@@ -1,15 +1,18 @@
import {Pipe, PipeTransform} from '@angular/core'; import {Pipe, PipeTransform} from '@angular/core';
import {SongType} from '../../../modules/songs/services/song.service';
@Pipe({ @Pipe({
name: 'songType', name: 'songType',
}) })
export class SongTypePipe implements PipeTransform { export class SongTypePipe implements PipeTransform {
public transform(songTypeKey: string): string { public transform(songTypeKey: SongType): string {
switch (songTypeKey) { switch (songTypeKey) {
case 'Worship': case 'Worship':
return 'Anbetung'; return 'Anbetung';
case 'Praise': case 'Praise':
return 'Lobpreis'; return 'Lobpreis';
case 'Misc':
return 'sonstiges';
default: default:
return ''; return '';
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 MiB

BIN
src/assets/bg-bible.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 575 KiB

BIN
src/assets/bg-dark-blue.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

BIN
src/assets/bg-leder.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 KiB

BIN
src/assets/bg-praise.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

View File

@@ -18,11 +18,8 @@ body {
overscroll-behavior-y: none; overscroll-behavior-y: none;
color: #333; color: #333;
background: #373b44; /* fallback for old browsers */
background: -webkit-linear-gradient(to bottom, #373b44, @primary-color); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to bottom, #373b44, @primary-color); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
background-attachment: fixed; background-attachment: fixed;
background: url("/assets/background.png"); background-image: url("/assets/background.jpg");
background-size: cover; background-size: cover;
} }