download handout
This commit is contained in:
@@ -12,7 +12,13 @@ import {Show} from './show';
|
|||||||
import {ChordMode} from '../../../widget-modules/components/song-text/song-text.component';
|
import {ChordMode} from '../../../widget-modules/components/song-text/song-text.component';
|
||||||
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 {ConfigService} from '../../../services/config.service';
|
||||||
|
import {Config} from '../../../services/config';
|
||||||
|
|
||||||
|
export interface DownloadOptions {
|
||||||
|
copyright?: boolean;
|
||||||
|
chordMode?: ChordMode;
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -25,20 +31,21 @@ export class DocxService {
|
|||||||
private songService: SongService,
|
private songService: SongService,
|
||||||
private textRenderingService: TextRenderingService,
|
private textRenderingService: TextRenderingService,
|
||||||
private userService: UserService,
|
private userService: UserService,
|
||||||
|
private configService: ConfigService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async create(showId: string): Promise<any> {
|
public async create(showId: string, options: DownloadOptions = {}): Promise<any> {
|
||||||
const {show, songs, user} = await this.prepareData(showId);
|
const {show, songs, user, config} = await this.prepareData(showId);
|
||||||
const type = new ShowTypePipe().transform(show.showType);
|
const type = new ShowTypePipe().transform(show.showType);
|
||||||
const title = `${type} ${show.date.toDate().toLocaleDateString()}`;
|
const title = `${type} ${show.date.toDate().toLocaleDateString()}`;
|
||||||
|
|
||||||
const paragraphs = [
|
const paragraphs = [
|
||||||
...this.renderTitle(title),
|
...this.renderTitle(title),
|
||||||
...this.renderSongs(songs),
|
...this.renderSongs(songs, options, config),
|
||||||
];
|
];
|
||||||
|
|
||||||
const document = this.prepareNewDocument(type, user.name);
|
const document = this.prepareNewDocument(type, user.name, options);
|
||||||
document.addSection({
|
document.addSection({
|
||||||
properties: {top: 400, bottom: 400, left: 400, right: 400},
|
properties: {top: 400, bottom: 400, left: 400, right: 400},
|
||||||
children: paragraphs,
|
children: paragraphs,
|
||||||
@@ -50,7 +57,7 @@ export class DocxService {
|
|||||||
this.saveAs(blob, `${title}.docx`);
|
this.saveAs(blob, `${title}.docx`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private prepareNewDocument(type: string, name: string): Document {
|
private prepareNewDocument(type: string, name: string, options: DownloadOptions): Document {
|
||||||
return new Document({
|
return new Document({
|
||||||
creator: name,
|
creator: name,
|
||||||
title: type,
|
title: type,
|
||||||
@@ -63,7 +70,15 @@ export class DocxService {
|
|||||||
basedOn: 'Normal',
|
basedOn: 'Normal',
|
||||||
next: 'Normal',
|
next: 'Normal',
|
||||||
quickFormat: true,
|
quickFormat: true,
|
||||||
run: {font: 'courier new'},
|
run: options?.chordMode === 'hide' ? {} : {font: 'courier new'},
|
||||||
|
paragraph: {indent: {left: 0}},
|
||||||
|
}, {
|
||||||
|
id: 'licence',
|
||||||
|
name: 'Lizenz',
|
||||||
|
basedOn: 'Normal',
|
||||||
|
next: 'Normal',
|
||||||
|
quickFormat: true,
|
||||||
|
run: {size: 15, color: 'grey'},
|
||||||
paragraph: {indent: {left: 0}},
|
paragraph: {indent: {left: 0}},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@@ -71,18 +86,20 @@ export class DocxService {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderSongs(songs: { showSong: ShowSong; song: Song; sections: Section[] }[]): Paragraph[] {
|
private renderSongs(songs: { showSong: ShowSong; song: Song; sections: Section[] }[], options: DownloadOptions, config: Config): Paragraph[] {
|
||||||
return songs.reduce((p, song) => [...p, ...this.renderSong(song.showSong, song.song, song.sections)], [])
|
return songs.reduce((p, song) => [...p, ...this.renderSong(song.showSong, song.song, song.sections, options, config)], [])
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderSong(showSong: ShowSong, song: Song, sections: Section[]): Paragraph[] {
|
private renderSong(showSong: ShowSong, song: Song, sections: Section[], options: DownloadOptions, config: Config): Paragraph[] {
|
||||||
const songTitle = this.renderSongTitle(song);
|
const songTitle = this.renderSongTitle(song);
|
||||||
const songText = this.renderSongText(sections, showSong.chordMode);
|
const copyright = this.renderCopyright(song, options, config);
|
||||||
|
const songText = this.renderSongText(sections, options?.chordMode ?? showSong.chordMode);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
songTitle,
|
songTitle,
|
||||||
|
copyright,
|
||||||
...songText
|
...songText
|
||||||
]
|
].filter(_ => _);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderSongText(sections: Section[], chordMode: ChordMode) {
|
private renderSongText(sections: Section[], chordMode: ChordMode) {
|
||||||
@@ -100,6 +117,23 @@ export class DocxService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderCopyright(song: Song, options: DownloadOptions, config: Config): Paragraph {
|
||||||
|
if (!options?.copyright) return null;
|
||||||
|
|
||||||
|
const label = song.label ? song.label + ', ' : '';
|
||||||
|
const artist = song.artist ? song.artist + ', ' : '';
|
||||||
|
const termsOfUse = song.termsOfUse ? song.termsOfUse + ', ' : '';
|
||||||
|
const origin = song.origin ? song.origin + ', ' : '';
|
||||||
|
const licence = song.legalOwner === 'CCLI'
|
||||||
|
? 'CCLI-Liednummer: ' + song.legalOwnerId + ', CCLI-Lizenz: ' + config.ccliLicenseId
|
||||||
|
: 'CCLI-Liednummer: ' + song.legalOwnerId;
|
||||||
|
|
||||||
|
return new Paragraph({
|
||||||
|
text: artist + label + termsOfUse + origin + licence,
|
||||||
|
style: 'licence',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private renderSection(section: Section, chordMode: ChordMode): Paragraph[] {
|
private renderSection(section: Section, chordMode: ChordMode): Paragraph[] {
|
||||||
return section.lines
|
return section.lines
|
||||||
@@ -138,9 +172,10 @@ export class DocxService {
|
|||||||
return [songTitle]
|
return [songTitle]
|
||||||
}
|
}
|
||||||
|
|
||||||
private async prepareData(showId: string): Promise<{ songs: ({ showSong: ShowSong, song: Song, sections: Section[] })[]; show: Show, user: User }> {
|
private async prepareData(showId: string): Promise<{ songs: ({ showSong: ShowSong, song: Song, sections: Section[] })[]; show: Show, user: User, config: Config }> {
|
||||||
const show = await this.showService.read$(showId).pipe(first()).toPromise();
|
const show = await this.showService.read$(showId).pipe(first()).toPromise();
|
||||||
const user = await this.userService.getUserbyId(show.owner);
|
const user = await this.userService.getUserbyId(show.owner);
|
||||||
|
const config = await this.configService.get();
|
||||||
|
|
||||||
const showSongs = await this.showSongService.list(showId);
|
const showSongs = await this.showSongService.list(showId);
|
||||||
const songsAsync = await showSongs.map(async showSong => {
|
const songsAsync = await showSongs.map(async showSong => {
|
||||||
@@ -153,7 +188,7 @@ export class DocxService {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
const songs = await Promise.all(songsAsync);
|
const songs = await Promise.all(songsAsync);
|
||||||
return {songs, show, user};
|
return {songs, show, user, config};
|
||||||
}
|
}
|
||||||
|
|
||||||
private saveAs(blob, fileName) {
|
private saveAs(blob, fileName) {
|
||||||
|
|||||||
@@ -40,7 +40,11 @@
|
|||||||
Veröffentlichung zurückziehen
|
Veröffentlichung zurückziehen
|
||||||
</app-button>
|
</app-button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<app-button (click)="onDownload()" [icon]="faDownload">Herunterladen</app-button>
|
<app-button [icon]="faDownload" [matMenuTriggerFor]="menu">Herunterladen</app-button>
|
||||||
|
<mat-menu #menu="matMenu">
|
||||||
|
<app-button (click)="onDownload()" [icon]="faUser">Ablauf für Lobpreisleiter</app-button>
|
||||||
|
<app-button (click)="onDownloadHandout()" [icon]="faUsers">Handout mit Copyright Infos</app-button>
|
||||||
|
</mat-menu>
|
||||||
</app-button-row>
|
</app-button-row>
|
||||||
</app-card>
|
</app-card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import {faBoxOpen} from '@fortawesome/free-solid-svg-icons/faBoxOpen';
|
|||||||
import {faExternalLinkAlt} from '@fortawesome/free-solid-svg-icons/faExternalLinkAlt';
|
import {faExternalLinkAlt} from '@fortawesome/free-solid-svg-icons/faExternalLinkAlt';
|
||||||
import {faLock} from '@fortawesome/free-solid-svg-icons/faLock';
|
import {faLock} from '@fortawesome/free-solid-svg-icons/faLock';
|
||||||
import {faFileDownload} from '@fortawesome/free-solid-svg-icons/faFileDownload';
|
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';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-show',
|
selector: 'app-show',
|
||||||
@@ -32,6 +34,8 @@ export class ShowComponent implements OnInit {
|
|||||||
public faPublish = faExternalLinkAlt;
|
public faPublish = faExternalLinkAlt;
|
||||||
public faUnpublish = faLock;
|
public faUnpublish = faLock;
|
||||||
public faDownload = faFileDownload;
|
public faDownload = faFileDownload;
|
||||||
|
public faUser = faUser;
|
||||||
|
public faUsers = faUsers;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private activatedRoute: ActivatedRoute,
|
private activatedRoute: ActivatedRoute,
|
||||||
@@ -80,4 +84,8 @@ export class ShowComponent implements OnInit {
|
|||||||
public async onDownload(): Promise<void> {
|
public async onDownload(): Promise<void> {
|
||||||
await this.docxService.create(this.showId);
|
await this.docxService.create(this.showId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async onDownloadHandout(): Promise<void> {
|
||||||
|
await this.docxService.create(this.showId, {chordMode: 'hide', copyright: true});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import {AddSongModule} from '../../widget-modules/components/add-song/add-song.m
|
|||||||
import {ButtonModule} from '../../widget-modules/components/button/button.module';
|
import {ButtonModule} from '../../widget-modules/components/button/button.module';
|
||||||
import {OwnerModule} from '../../services/user/owner.module';
|
import {OwnerModule} from '../../services/user/owner.module';
|
||||||
import {UserNameModule} from '../../services/user/user-name/user-name.module';
|
import {UserNameModule} from '../../services/user/user-name/user-name.module';
|
||||||
|
import {MatMenuModule} from '@angular/material/menu';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@@ -55,6 +56,7 @@ import {UserNameModule} from '../../services/user/user-name/user-name.module';
|
|||||||
ButtonModule,
|
ButtonModule,
|
||||||
OwnerModule,
|
OwnerModule,
|
||||||
UserNameModule,
|
UserNameModule,
|
||||||
|
MatMenuModule,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class ShowsModule {
|
export class ShowsModule {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {Injectable} from '@angular/core';
|
|||||||
import {DbService} from './db.service';
|
import {DbService} from './db.service';
|
||||||
import {Observable} from 'rxjs';
|
import {Observable} from 'rxjs';
|
||||||
import {Config} from './config';
|
import {Config} from './config';
|
||||||
|
import {first} from 'rxjs/operators';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -13,4 +14,8 @@ export class ConfigService {
|
|||||||
public get get$(): Observable<Config> {
|
public get get$(): Observable<Config> {
|
||||||
return this.db.doc$<Config>('global/config');
|
return this.db.doc$<Config>('global/config');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async get(): Promise<Config> {
|
||||||
|
return await this.db.doc$<Config>('global/config').pipe(first()).toPromise();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export class UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getUserbyId(userId: string): Promise<User> {
|
public getUserbyId(userId: string): Promise<User> {
|
||||||
return this.getUserbyId$('users/' + userId).pipe(first()).toPromise();
|
return this.getUserbyId$(userId).pipe(first()).toPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getUserbyId$(userId: string): Observable<User> {
|
public getUserbyId$(userId: string): Observable<User> {
|
||||||
|
|||||||
@@ -10,3 +10,8 @@ button {
|
|||||||
display: none ;
|
display: none ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fa-icon {
|
||||||
|
width: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user