From 2023f2b561853f3c439ffeb4bcbd1a2d277f23b2 Mon Sep 17 00:00:00 2001 From: smuddyx Date: Thu, 28 May 2020 21:59:10 +0200 Subject: [PATCH] download handout --- .../modules/shows/services/docx.service.ts | 61 +++++++++++++++---- .../modules/shows/show/show.component.html | 6 +- src/app/modules/shows/show/show.component.ts | 8 +++ src/app/modules/shows/shows.module.ts | 2 + src/app/services/config.service.ts | 5 ++ src/app/services/user/user.service.ts | 2 +- .../components/button/button.component.less | 5 ++ 7 files changed, 74 insertions(+), 15 deletions(-) diff --git a/src/app/modules/shows/services/docx.service.ts b/src/app/modules/shows/services/docx.service.ts index 9d52792..5ae7ac2 100644 --- a/src/app/modules/shows/services/docx.service.ts +++ b/src/app/modules/shows/services/docx.service.ts @@ -12,7 +12,13 @@ import {Show} from './show'; import {ChordMode} from '../../../widget-modules/components/song-text/song-text.component'; import {UserService} from '../../../services/user/user.service'; 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({ providedIn: 'root' @@ -25,20 +31,21 @@ export class DocxService { private songService: SongService, private textRenderingService: TextRenderingService, private userService: UserService, + private configService: ConfigService, ) { } - public async create(showId: string): Promise { - const {show, songs, user} = await this.prepareData(showId); + public async create(showId: string, options: DownloadOptions = {}): Promise { + const {show, songs, user, config} = await this.prepareData(showId); const type = new ShowTypePipe().transform(show.showType); const title = `${type} ${show.date.toDate().toLocaleDateString()}`; const paragraphs = [ ...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({ properties: {top: 400, bottom: 400, left: 400, right: 400}, children: paragraphs, @@ -50,7 +57,7 @@ export class DocxService { this.saveAs(blob, `${title}.docx`); } - private prepareNewDocument(type: string, name: string): Document { + private prepareNewDocument(type: string, name: string, options: DownloadOptions): Document { return new Document({ creator: name, title: type, @@ -63,7 +70,15 @@ export class DocxService { basedOn: 'Normal', next: 'Normal', 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}}, }, ] @@ -71,18 +86,20 @@ export class DocxService { }) } - private renderSongs(songs: { showSong: ShowSong; song: Song; sections: Section[] }[]): Paragraph[] { - return songs.reduce((p, song) => [...p, ...this.renderSong(song.showSong, song.song, song.sections)], []) + 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, 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 songText = this.renderSongText(sections, showSong.chordMode); + const copyright = this.renderCopyright(song, options, config); + const songText = this.renderSongText(sections, options?.chordMode ?? showSong.chordMode); return [ songTitle, + copyright, ...songText - ] + ].filter(_ => _); } 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[] { return section.lines @@ -138,9 +172,10 @@ export class DocxService { 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 user = await this.userService.getUserbyId(show.owner); + const config = await this.configService.get(); const showSongs = await this.showSongService.list(showId); const songsAsync = await showSongs.map(async showSong => { @@ -153,7 +188,7 @@ export class DocxService { } }) const songs = await Promise.all(songsAsync); - return {songs, show, user}; + return {songs, show, user, config}; } private saveAs(blob, fileName) { diff --git a/src/app/modules/shows/show/show.component.html b/src/app/modules/shows/show/show.component.html index f015a09..ccc0ddc 100644 --- a/src/app/modules/shows/show/show.component.html +++ b/src/app/modules/shows/show/show.component.html @@ -40,7 +40,11 @@ Veröffentlichung zurückziehen - Herunterladen + Herunterladen + + Ablauf für Lobpreisleiter + Handout mit Copyright Infos + diff --git a/src/app/modules/shows/show/show.component.ts b/src/app/modules/shows/show/show.component.ts index 98c21bf..f5e2911 100644 --- a/src/app/modules/shows/show/show.component.ts +++ b/src/app/modules/shows/show/show.component.ts @@ -14,6 +14,8 @@ 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'; @Component({ selector: 'app-show', @@ -32,6 +34,8 @@ export class ShowComponent implements OnInit { public faPublish = faExternalLinkAlt; public faUnpublish = faLock; public faDownload = faFileDownload; + public faUser = faUser; + public faUsers = faUsers; constructor( private activatedRoute: ActivatedRoute, @@ -80,4 +84,8 @@ export class ShowComponent implements OnInit { public async onDownload(): Promise { await this.docxService.create(this.showId); } + + public async onDownloadHandout(): Promise { + await this.docxService.create(this.showId, {chordMode: 'hide', copyright: true}); + } } diff --git a/src/app/modules/shows/shows.module.ts b/src/app/modules/shows/shows.module.ts index aa2ec65..da539b0 100644 --- a/src/app/modules/shows/shows.module.ts +++ b/src/app/modules/shows/shows.module.ts @@ -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 {OwnerModule} from '../../services/user/owner.module'; import {UserNameModule} from '../../services/user/user-name/user-name.module'; +import {MatMenuModule} from '@angular/material/menu'; @NgModule({ @@ -55,6 +56,7 @@ import {UserNameModule} from '../../services/user/user-name/user-name.module'; ButtonModule, OwnerModule, UserNameModule, + MatMenuModule, ] }) export class ShowsModule { diff --git a/src/app/services/config.service.ts b/src/app/services/config.service.ts index f213be3..0a9a0ce 100644 --- a/src/app/services/config.service.ts +++ b/src/app/services/config.service.ts @@ -2,6 +2,7 @@ import {Injectable} from '@angular/core'; import {DbService} from './db.service'; import {Observable} from 'rxjs'; import {Config} from './config'; +import {first} from 'rxjs/operators'; @Injectable({ providedIn: 'root' @@ -13,4 +14,8 @@ export class ConfigService { public get get$(): Observable { return this.db.doc$('global/config'); } + + public async get(): Promise { + return await this.db.doc$('global/config').pipe(first()).toPromise(); + } } diff --git a/src/app/services/user/user.service.ts b/src/app/services/user/user.service.ts index 79a7b3f..94a06c5 100644 --- a/src/app/services/user/user.service.ts +++ b/src/app/services/user/user.service.ts @@ -32,7 +32,7 @@ export class UserService { } public getUserbyId(userId: string): Promise { - return this.getUserbyId$('users/' + userId).pipe(first()).toPromise(); + return this.getUserbyId$(userId).pipe(first()).toPromise(); } public getUserbyId$(userId: string): Observable { diff --git a/src/app/widget-modules/components/button/button.component.less b/src/app/widget-modules/components/button/button.component.less index 9c5745c..7704009 100644 --- a/src/app/widget-modules/components/button/button.component.less +++ b/src/app/widget-modules/components/button/button.component.less @@ -10,3 +10,8 @@ button { display: none ; } } + +fa-icon { + width: 20px; + display: inline-block; +}