list file attachments

This commit is contained in:
2020-05-13 19:31:57 +02:00
committed by smuddy
parent 536739e651
commit 80e35a7e44
23 changed files with 300 additions and 53 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,25 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {LogoComponent} from './logo.component';
describe('LogoComponent', () => {
let component: LogoComponent;
let fixture: ComponentFixture<LogoComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [LogoComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LogoComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,16 @@
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'app-logo',
templateUrl: './logo.component.html',
styleUrls: ['./logo.component.less']
})
export class LogoComponent implements OnInit {
constructor() {
}
ngOnInit(): void {
}
}

View File

@@ -1,5 +1,20 @@
<div *ngIf="song" [style.font-size.px]="zoom" class="fullscreen"> <div *ngIf="song" [style.font-size.px]="zoom" class="fullscreen background">
<app-song-text [fullscreen]="true" [index]="index" [showSwitch]="false" [text]="song.text"
chordMode="hide"></app-song-text>
<app-legal [config]="config$|async" [song]="song"></app-legal> <div @songSwitch [class.blur]="songId==='title'" [class.hide]="songId!=='title' && songId!=='empty'"
class="start fullscreen logo">
<app-logo></app-logo>
</div>
<div *ngIf="songId==='title'" @songSwitch class="start fullscreen">
<div>{{showType|showType}}</div>
<div class="date">{{date|date:'dd.MM.yyyy'}}</div>
</div>
<app-song-text *ngIf="songId!=='title' && songId!=='empty'" @songSwitch [fullscreen]="true" [index]="index"
[showSwitch]="false" [text]="song.text"
chordMode="hide"></app-song-text>
<app-legal *ngIf="songId!=='title' && songId!=='empty'" @songSwitch [config]="config$|async"
[song]="song"></app-legal>
</div> </div>

View File

@@ -8,15 +8,52 @@
left: 0; left: 0;
bottom: 0; bottom: 0;
right: 0; right: 0;
background: black;
z-index: 1; z-index: 1;
display: flex;
cursor: none;
}
.background {
background: black;
padding: 50px; padding: 50px;
color: white; color: white;
display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
transition: 300ms all ease-in-out; transition: 300ms all ease-in-out;
} }
.start {
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
flex-direction: column;
font-size: 3em;
box-sizing: border-box;
text-shadow: 0 0 10px black, 0 0 20px black, 0 0 40px black;
.date {
font-size: 0.6em;
}
}
.logo {
transform: scale(0.9);
opacity: 1;
filter: blur(0px);
transition: all 5s ease-in-out;
}
.blur {
filter: blur(10px);
opacity: 0.5;
}
.hide {
filter: blur(30px);
opacity: 0.1;
transform: scale(0.8) translateY(-10%);
}

View File

@@ -8,16 +8,22 @@ import {GlobalSettingsService} from '../../../services/global-settings.service';
import {Config} from '../../../services/config'; import {Config} from '../../../services/config';
import {Observable} from 'rxjs'; 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';
@Component({ @Component({
selector: 'app-monitor', selector: 'app-monitor',
templateUrl: './monitor.component.html', templateUrl: './monitor.component.html',
styleUrls: ['./monitor.component.less'] styleUrls: ['./monitor.component.less'],
animations: [songSwitch]
}) })
export class MonitorComponent implements OnInit { export class MonitorComponent implements OnInit {
public song: Song; public song: Song;
public zoom: number; public zoom: number;
public currentShowId: string;
public songId: string;
public index: number; public index: number;
public showType: string;
public date: Date;
private sections: Section[]; private sections: Section[];
public config$: Observable<Config>; public config$: Observable<Config>;
@@ -35,11 +41,15 @@ export class MonitorComponent implements OnInit {
this.globalSettingsService.get$.pipe( this.globalSettingsService.get$.pipe(
map(_ => _.currentShow), map(_ => _.currentShow),
distinctUntilChanged(), distinctUntilChanged(),
tap(_ => this.currentShowId = _),
switchMap(_ => this.showService.read$(_)), switchMap(_ => this.showService.read$(_)),
tap(_ => this.showType = _.showType),
tap(_ => this.date = _.date.toDate()),
tap(_ => this.songId = _.presentationSongId),
tap(_ => this.index = _.presentationSection), tap(_ => this.index = _.presentationSection),
tap(_ => this.zoom = _.presentationZoom ?? 30), tap(_ => this.zoom = _.presentationZoom ?? 30),
switchMap(_ => this.songService.read$(_.presentationSongId)) switchMap(_ => this.songService.read$(_.presentationSongId))
).subscribe(_ => { ).subscribe((_: Song) => {
this.song = _; this.song = _;
this.sections = this.textRenderingService.parse(_.text); this.sections = this.textRenderingService.parse(_.text);
}); });

View File

@@ -16,10 +16,11 @@ import {FontAwesomeModule} from '@fortawesome/angular-fontawesome';
import {MatSliderModule} from '@angular/material/slider'; import {MatSliderModule} from '@angular/material/slider';
import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {AddSongModule} from '../../widget-modules/components/add-song/add-song.module'; import {AddSongModule} from '../../widget-modules/components/add-song/add-song.module';
import {LogoComponent} from './monitor/logo/logo.component';
@NgModule({ @NgModule({
declarations: [MonitorComponent, RemoteComponent, LegalComponent], declarations: [MonitorComponent, RemoteComponent, LegalComponent, LogoComponent],
imports: [ imports: [
CommonModule, CommonModule,
PresentationRoutingModule, PresentationRoutingModule,

View File

@@ -12,6 +12,20 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<ng-container *ngIf="!progress">
<div *ngIf="show" class="song-parts padding-bottom">
<div (click)="onSectionClick('title', -1)"
[class.active]="show.presentationSongId==='title'"
class="song-part">
<div class="head">Veranstaltung</div>
</div>
<div (click)="onSectionClick('empty', -1)"
[class.active]="show.presentationSongId==='empty'"
class="song-part">
<div class="head">Leer</div>
</div>
</div>
<div *ngFor="let song of presentationSongs" @fade class="song"> <div *ngFor="let song of presentationSongs" @fade class="song">
<div [class.active]="show.presentationSongId===song.id" class="title song-part"> <div [class.active]="show.presentationSongId===song.id" class="title song-part">
<div (click)="onSectionClick(song.id, -1)" class="head">{{song.title}}</div> <div (click)="onSectionClick(song.id, -1)" class="head">{{song.title}}</div>
@@ -45,6 +59,7 @@
<app-add-song *ngIf="show" [addedLive]="true" [showId]="currentShowId" [showSongs]="showSongs" <app-add-song *ngIf="show" [addedLive]="true" [showId]="currentShowId" [showSongs]="showSongs"
[songs]="songs"></app-add-song> [songs]="songs"></app-add-song>
</ng-container>
</app-card> </app-card>

View File

@@ -68,3 +68,7 @@
display: grid; display: grid;
grid-template-columns: 40px auto; grid-template-columns: 40px auto;
} }
.padding-bottom {
padding-bottom: 20px;
}

View File

@@ -12,6 +12,7 @@ import {GlobalSettingsService} from '../../../services/global-settings.service';
import {FormControl} from '@angular/forms'; import {FormControl} from '@angular/forms';
import {distinctUntilChanged, map} from 'rxjs/operators'; import {distinctUntilChanged, map} from 'rxjs/operators';
import {fade} from '../../../animations'; import {fade} from '../../../animations';
import {delay} from '../../../services/delay';
export interface PresentationSong { export interface PresentationSong {
id: string; id: string;
@@ -32,6 +33,7 @@ export class RemoteComponent {
public songs: Song[]; public songs: Song[];
public presentationSongs: PresentationSong[]; public presentationSongs: PresentationSong[];
public currentShowId: string; public currentShowId: string;
public progress = false;
public faDesktop = faDesktop; public faDesktop = faDesktop;
public showControl = new FormControl(); public showControl = new FormControl();
@@ -49,12 +51,21 @@ export class RemoteComponent {
globalSettingsService.get$.pipe( globalSettingsService.get$.pipe(
map(_ => _.currentShow), map(_ => _.currentShow),
distinctUntilChanged() distinctUntilChanged()
).subscribe(_ => this.showControl.setValue(_)); ).subscribe(_ => {
this.showControl.setValue(_, {emitEvent: false});
this.onShowChanged(_, false);
});
this.showControl.valueChanges.subscribe(value => this.onShowChanged(value)); this.showControl.valueChanges.subscribe(value => this.onShowChanged(value));
} }
public onShowChanged(change: string): void { public async onShowChanged(change: string, updateShow = true): Promise<void> {
this.globalSettingsService.set({currentShow: change}); this.progress = true;
if (updateShow) {
await this.showService.update$(change, {presentationSongId: 'empty'});
await delay(1200);
await this.globalSettingsService.set({currentShow: change});
await this.showService.update$(change, {presentationSongId: 'title'});
}
this.currentShowId = change; this.currentShowId = change;
this.showService.read$(change).subscribe(_ => this.show = _); this.showService.read$(change).subscribe(_ => this.show = _);
this.showSongService.list$(change).subscribe(_ => { this.showSongService.list$(change).subscribe(_ => {
@@ -67,6 +78,8 @@ export class RemoteComponent {
sections: this.textRenderingService.parse(song.text) sections: this.textRenderingService.parse(song.text)
})) }))
}); });
await delay(500);
this.progress = false;
} }
public getFirstLine(section: Section): string { public getFirstLine(section: Section): string {

View File

@@ -18,5 +18,9 @@
<mat-icon>cloud_upload</mat-icon> <mat-icon>cloud_upload</mat-icon>
</button> </button>
</div> </div>
<p *ngFor="let file of (files$|async)">
<app-file [file]="file"></app-file>
</p>
</app-card> </app-card>

View File

@@ -2,7 +2,10 @@ import {Component} from '@angular/core';
import {Upload} from '../../../services/upload'; import {Upload} from '../../../services/upload';
import {UploadService} from '../../../services/upload.service'; import {UploadService} from '../../../services/upload.service';
import {ActivatedRoute} from '@angular/router'; import {ActivatedRoute} from '@angular/router';
import {map} from 'rxjs/operators'; import {map, switchMap} from 'rxjs/operators';
import {FileDataService} from '../../../services/file-data.service';
import {Observable} from 'rxjs';
import {File} from '../../../services/file';
@Component({ @Component({
selector: 'app-edit-file', selector: 'app-edit-file',
@@ -14,13 +17,24 @@ export class EditFileComponent {
public selectedFiles: FileList; public selectedFiles: FileList;
public currentUpload: Upload; public currentUpload: Upload;
public songId: string; public songId: string;
public files$: Observable<File[]>;
constructor(private activatedRoute: ActivatedRoute, private uploadService: UploadService) {
constructor(
private activatedRoute: ActivatedRoute,
private uploadService: UploadService,
private fileService: FileDataService,
) {
this.activatedRoute.params.pipe( this.activatedRoute.params.pipe(
map(param => param.songId), map(param => param.songId),
).subscribe(songId => { ).subscribe(songId => {
this.songId = songId; this.songId = songId;
}); });
this.files$ = this.activatedRoute.params.pipe(
map(param => param.songId),
switchMap(songId => this.fileService.read$(songId))
);
} }
detectFiles(event) { detectFiles(event) {

View File

@@ -1 +1,3 @@
<p>file works!</p> <a [href]="url$|async" target="_blank">
{{name}}
</a>

View File

@@ -1,4 +1,7 @@
import {Component, OnInit} from '@angular/core'; import {Component, Input, OnInit} from '@angular/core';
import {Observable} from 'rxjs';
import {File} from '../../../../services/file';
import {AngularFireStorage} from '@angular/fire/storage';
@Component({ @Component({
selector: 'app-file', selector: 'app-file',
@@ -6,11 +9,20 @@ import {Component, OnInit} from '@angular/core';
styleUrls: ['./file.component.less'] styleUrls: ['./file.component.less']
}) })
export class FileComponent implements OnInit { export class FileComponent implements OnInit {
public url$: Observable<string>;
public name: string;
constructor() { constructor(private storage: AngularFireStorage) {
} }
ngOnInit() { @Input() set file(file: File) {
}
const ref = this.storage.ref(file.path + '/' + file.name);
this.url$ = ref.getDownloadURL();
this.name = file.name;
};
ngOnInit(): void {
}
} }

View File

@@ -0,0 +1,3 @@
<a [href]="url$|async" target="_blank">
{{name}}
</a>

View File

@@ -0,0 +1,25 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {FileComponent} from './file.component';
describe('FileComponent', () => {
let component: FileComponent;
let fixture: ComponentFixture<FileComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [FileComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FileComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,29 @@
import {Component, Input, OnInit} from '@angular/core';
import {File} from '../../services/file';
import {AngularFireStorage} from '@angular/fire/storage';
import {Observable} from 'rxjs';
@Component({
selector: 'app-file',
templateUrl: './file.component.html',
styleUrls: ['./file.component.less']
})
export class FileComponent implements OnInit {
public url$: Observable<string>;
public name: string;
constructor(private storage: AngularFireStorage) {
}
@Input() set file(file: File) {
const ref = this.storage.ref(file.path + '/' + file.name);
this.url$ = ref.getDownloadURL();
this.name = file.name;
};
ngOnInit(): void {
}
}

View File

@@ -35,6 +35,8 @@
</app-card> </app-card>
<app-card *ngIf="!!(files$|async)" heading="Anhänge"> <app-card *ngIf="!!(files$|async)" heading="Anhänge">
<div *ngFor="let file of (files$|async)">{{file.name}}</div> <p *ngFor="let file of (files$|async)">
<app-file [file]="file"></app-file>
</p>
</app-card> </app-card>
</div> </div>

View File

@@ -12,10 +12,11 @@ import {MatChipsModule} from '@angular/material/chips';
import {RoleModule} from '../../../services/user/role.module'; import {RoleModule} from '../../../services/user/role.module';
import {StatusTranslaterModule} from '../../../widget-modules/pipes/status-translater/status-translater.module'; import {StatusTranslaterModule} from '../../../widget-modules/pipes/status-translater/status-translater.module';
import {ButtonModule} from '../../../widget-modules/components/button/button.module'; import {ButtonModule} from '../../../widget-modules/components/button/button.module';
import {FileComponent} from './file/file.component';
@NgModule({ @NgModule({
declarations: [SongComponent], declarations: [SongComponent, FileComponent],
exports: [SongComponent], exports: [SongComponent],
imports: [ imports: [
CommonModule, CommonModule,

View File

@@ -9,10 +9,12 @@ export const songSwitch = // the fade-in/fade-out animation.
// fade in when created. this could also be written as transition('void => *') // fade in when created. this could also be written as transition('void => *')
transition(':enter', [ transition(':enter', [
style({opacity: 0}), style({opacity: 0}),
animate(600) animate(1200, style({opacity: 0})),
animate(1200, style({opacity: 1})),
]), ]),
// fade out when destroyed. this could also be written as transition('void => *') // fade out when destroyed. this could also be written as transition('void => *')
transition(':leave', transition(':leave',
animate(600, style({opacity: 0}))) animate(1200, style({opacity: 0}))
)
]) ])

View File

@@ -46,9 +46,9 @@ export class SongTextComponent implements OnInit {
} }
ngOnInit(): void { public ngOnInit(): void {
setInterval(() => { setInterval(() => {
if (!this.fullscreen || this.index === -1) { if (!this.fullscreen || this.index === -1 || !this.viewSections.toArray()[this.index]) {
this.offset = 0; this.offset = 0;
return; return;
} }
@@ -79,13 +79,12 @@ export class SongTextComponent implements OnInit {
this.chordModeChanged.emit(next); this.chordModeChanged.emit(next);
} }
public onClick() { public onClick(): void {
scrollTo(0, this.elRef.nativeElement.offsetTop - 20); scrollTo(0, this.elRef.nativeElement.offsetTop - 20);
} }
public checkDisabled(i: number) { public checkDisabled(i: number): boolean {
return this.index !== -1 && this.index !== i; return this.index !== -1 && this.index !== i;
} }
private getNextChordMode(): ChordMode { private getNextChordMode(): ChordMode {