diff --git a/WEB/src/app/app-routing.module.ts b/WEB/src/app/app-routing.module.ts index 0f2aaf3..69bc162 100644 --- a/WEB/src/app/app-routing.module.ts +++ b/WEB/src/app/app-routing.module.ts @@ -1,21 +1,22 @@ -import { SongsComponent } from './components/songs/songs.component'; -import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; +import {SongsComponent} from './components/songs/songs.component'; +import {NgModule} from '@angular/core'; +import {RouterModule, Routes} from '@angular/router'; const routes: Routes = [ - { - path: 'songs', - component: SongsComponent - }, - { - path: '', - redirectTo: 'songs', - pathMatch: 'full' - } + { + path: 'songs', + component: SongsComponent + }, + { + path: '', + redirectTo: 'songs', + pathMatch: 'full' + } ]; @NgModule({ - imports: [RouterModule.forRoot(routes)], - exports: [RouterModule] + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule] }) -export class AppRoutingModule { } +export class AppRoutingModule { +} diff --git a/WEB/src/app/app.component.html b/WEB/src/app/app.component.html index 79be59c..0680b43 100644 --- a/WEB/src/app/app.component.html +++ b/WEB/src/app/app.component.html @@ -1,2 +1 @@ - diff --git a/WEB/src/app/app.component.ts b/WEB/src/app/app.component.ts index ea64448..b3ef2f6 100644 --- a/WEB/src/app/app.component.ts +++ b/WEB/src/app/app.component.ts @@ -1,8 +1,9 @@ -import { Component } from '@angular/core'; +import {Component} from '@angular/core'; @Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.less'] + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.less'] }) -export class AppComponent { } +export class AppComponent { +} diff --git a/WEB/src/app/app.module.ts b/WEB/src/app/app.module.ts index 3a2e677..eb2c90c 100644 --- a/WEB/src/app/app.module.ts +++ b/WEB/src/app/app.module.ts @@ -1,69 +1,70 @@ -import { BrowserModule } from '@angular/platform-browser'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { NgModule } from '@angular/core'; -import { ReactiveFormsModule, FormsModule } from '@angular/forms'; -import { ODataModule } from 'odata-v4-ng'; +import {BrowserModule} from '@angular/platform-browser'; +import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {NgModule} from '@angular/core'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {ODataModule} from 'odata-v4-ng'; -import { AppRoutingModule } from './app-routing.module'; -import { AppComponent } from './app.component'; -import { HttpClientModule } from '@angular/common/http'; -import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; +import {AppRoutingModule} from './app-routing.module'; +import {AppComponent} from './app.component'; +import {HttpClientModule} from '@angular/common/http'; +import {FontAwesomeModule} from '@fortawesome/angular-fontawesome'; -import { MatInputModule } from '@angular/material/input'; -import { MatTableModule } from '@angular/material/table'; -import { MatCardModule } from '@angular/material/card'; -import { MatButtonModule } from '@angular/material/button'; -import { MatChipsModule } from '@angular/material/chips'; -import { MatRadioModule } from '@angular/material/radio'; -import { MatSelectModule } from '@angular/material/select'; -import { MatTooltipModule } from '@angular/material/tooltip'; -import { MatProgressBarModule } from '@angular/material/progress-bar'; +import {MatInputModule} from '@angular/material/input'; +import {MatTableModule} from '@angular/material/table'; +import {MatCardModule} from '@angular/material/card'; +import {MatButtonModule} from '@angular/material/button'; +import {MatChipsModule} from '@angular/material/chips'; +import {MatRadioModule} from '@angular/material/radio'; +import {MatSelectModule} from '@angular/material/select'; +import {MatTooltipModule} from '@angular/material/tooltip'; +import {MatProgressBarModule} from '@angular/material/progress-bar'; -import { TableComponent } from './components/songs/table/table.component'; -import { SongsComponent } from './components/songs/songs.component'; -import { SongComponent } from './components/songs/song/song.component'; -import { SongEditComponent } from './components/songs/song-edit/song-edit.component'; -import { SongNewComponent } from './components/songs/song-new/song-new.component'; -import { SongFormComponent } from './components/songs/song-form/song-form.component'; -import { SongFilesComponent } from './components/songs/song-files/song-files.component'; -import { FileUploadModule } from 'ng2-file-upload'; -import { SongFileEditComponent } from './components/songs/song-file-edit/song-file-edit.component'; +import {TableComponent} from './components/songs/table/table.component'; +import {SongsComponent} from './components/songs/songs.component'; +import {SongComponent} from './components/songs/song/song.component'; +import {SongEditComponent} from './components/songs/song-edit/song-edit.component'; +import {SongNewComponent} from './components/songs/song-new/song-new.component'; +import {SongFormComponent} from './components/songs/song-form/song-form.component'; +import {SongFilesComponent} from './components/songs/song-files/song-files.component'; +import {FileUploadModule} from 'ng2-file-upload'; +import {SongFileEditComponent} from './components/songs/song-file-edit/song-file-edit.component'; @NgModule({ - declarations: [ - AppComponent, - SongsComponent, - TableComponent, - SongComponent, - SongEditComponent, - SongNewComponent, - SongFormComponent, - SongFilesComponent, - SongFileEditComponent - ], - imports: [ - BrowserModule, - BrowserAnimationsModule, - FormsModule, - ReactiveFormsModule, - HttpClientModule, - ODataModule, + declarations: [ + AppComponent, + SongsComponent, + TableComponent, + SongComponent, + SongEditComponent, + SongNewComponent, + SongFormComponent, + SongFilesComponent, + SongFileEditComponent + ], + imports: [ + BrowserModule, + BrowserAnimationsModule, + FormsModule, + ReactiveFormsModule, + HttpClientModule, + ODataModule, - MatInputModule, - MatCardModule, - MatTableModule, - MatButtonModule, - MatChipsModule, - MatRadioModule, - MatSelectModule, - MatTooltipModule, - MatProgressBarModule, + MatInputModule, + MatCardModule, + MatTableModule, + MatButtonModule, + MatChipsModule, + MatRadioModule, + MatSelectModule, + MatTooltipModule, + MatProgressBarModule, - FontAwesomeModule, - FileUploadModule, - AppRoutingModule, - ], - providers: [], - bootstrap: [AppComponent] + FontAwesomeModule, + FileUploadModule, + AppRoutingModule, + ], + providers: [], + bootstrap: [AppComponent] }) -export class AppModule {} +export class AppModule { +} diff --git a/WEB/src/app/components/songs/song-edit/song-edit.component.html b/WEB/src/app/components/songs/song-edit/song-edit.component.html index fd81955..d671e4a 100644 --- a/WEB/src/app/components/songs/song-edit/song-edit.component.html +++ b/WEB/src/app/components/songs/song-edit/song-edit.component.html @@ -1,24 +1,24 @@
- - -
- -
- Titel bearbeiten - - Daten werden nach der Eingabe automatisch gespeichert - -
- - - - -
+ + +
+ +
+ Titel bearbeiten + + Daten werden nach der Eingabe automatisch gespeichert + +
+ + + + +
diff --git a/WEB/src/app/components/songs/song-edit/song-edit.component.less b/WEB/src/app/components/songs/song-edit/song-edit.component.less index 9ea5fbf..5d4e87f 100644 --- a/WEB/src/app/components/songs/song-edit/song-edit.component.less +++ b/WEB/src/app/components/songs/song-edit/song-edit.component.less @@ -1,3 +1,3 @@ :host { - display: block; - } \ No newline at end of file + display: block; +} diff --git a/WEB/src/app/components/songs/song-edit/song-edit.component.ts b/WEB/src/app/components/songs/song-edit/song-edit.component.ts index 925a8d6..9a6ead6 100644 --- a/WEB/src/app/components/songs/song-edit/song-edit.component.ts +++ b/WEB/src/app/components/songs/song-edit/song-edit.component.ts @@ -1,38 +1,34 @@ -import { SongsService } from 'src/app/data/songs.service'; -import { FormGroup } from '@angular/forms'; -import { - Component, - OnInit, - ChangeDetectionStrategy, - ChangeDetectorRef -} from '@angular/core'; -import { EditSongService } from 'src/app/data/edit-song.service'; -import { faLongArrowAltLeft } from '@fortawesome/free-solid-svg-icons'; -import { State } from 'src/app/data/state'; +import {SongsService} from 'src/app/data/songs.service'; +import {FormGroup} from '@angular/forms'; +import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit} from '@angular/core'; +import {EditSongService} from 'src/app/data/edit-song.service'; +import {faLongArrowAltLeft} from '@fortawesome/free-solid-svg-icons'; +import {State} from 'src/app/data/state'; @Component({ - selector: 'app-song-edit', - templateUrl: './song-edit.component.html', - styleUrls: ['./song-edit.component.less'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'app-song-edit', + templateUrl: './song-edit.component.html', + styleUrls: ['./song-edit.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush }) export class SongEditComponent implements OnInit { - public form: FormGroup = null; - public faArrow = faLongArrowAltLeft; + public form: FormGroup = null; + public faArrow = faLongArrowAltLeft; - constructor( - private editSongService: EditSongService, - private songsService: SongsService, - private change: ChangeDetectorRef - ) {} + constructor( + private editSongService: EditSongService, + private songsService: SongsService, + private change: ChangeDetectorRef + ) { + } - ngOnInit() { - this.form = this.editSongService.initSongEditForm(true); - this.change.markForCheck(); - } + ngOnInit() { + this.form = this.editSongService.initSongEditForm(true); + this.change.markForCheck(); + } - public onBack(): void { - this.songsService.state = State.read; - } + public onBack(): void { + this.songsService.state = State.read; + } } diff --git a/WEB/src/app/components/songs/song-file-edit/song-file-edit.component.html b/WEB/src/app/components/songs/song-file-edit/song-file-edit.component.html index 87b48e4..e0aa6ea 100644 --- a/WEB/src/app/components/songs/song-file-edit/song-file-edit.component.html +++ b/WEB/src/app/components/songs/song-file-edit/song-file-edit.component.html @@ -1,17 +1,17 @@
- - - - - Art - - - {{ type.text }} - - - + + + + + Art + + + {{ type.text }} + + +
diff --git a/WEB/src/app/components/songs/song-file-edit/song-file-edit.component.less b/WEB/src/app/components/songs/song-file-edit/song-file-edit.component.less index 63ccc69..59b9555 100644 --- a/WEB/src/app/components/songs/song-file-edit/song-file-edit.component.less +++ b/WEB/src/app/components/songs/song-file-edit/song-file-edit.component.less @@ -1,6 +1,6 @@ form { - display: grid; - grid-template-columns: 2fr 1fr; - grid-column-gap: 10px; - padding-top: 10px; -} \ No newline at end of file + display: grid; + grid-template-columns: 2fr 1fr; + grid-column-gap: 10px; + padding-top: 10px; +} diff --git a/WEB/src/app/components/songs/song-file-edit/song-file-edit.component.ts b/WEB/src/app/components/songs/song-file-edit/song-file-edit.component.ts index 66c1418..ee9ad8d 100644 --- a/WEB/src/app/components/songs/song-file-edit/song-file-edit.component.ts +++ b/WEB/src/app/components/songs/song-file-edit/song-file-edit.component.ts @@ -1,50 +1,44 @@ -import { SongsService } from './../../../data/songs.service'; -import { FileType } from './../../../models/files-types.model.ts'; -import { FormGroup } from '@angular/forms'; -import { - Component, - OnInit, - OnDestroy, - Input, - Output, - EventEmitter -} from '@angular/core'; -import { EditSongService } from 'src/app/data/edit-song.service'; -import { Subscription } from 'rxjs'; +import {SongsService} from '../../../data/songs.service'; +import {FileType} from '../../../models/files-types.model.ts'; +import {FormGroup} from '@angular/forms'; +import {Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core'; +import {EditSongService} from 'src/app/data/edit-song.service'; +import {Subscription} from 'rxjs'; @Component({ - selector: 'app-song-file-edit', - templateUrl: './song-file-edit.component.html', - styleUrls: ['./song-file-edit.component.less'] + selector: 'app-song-file-edit', + templateUrl: './song-file-edit.component.html', + styleUrls: ['./song-file-edit.component.less'] }) export class SongFileEditComponent implements OnInit, OnDestroy { - @Input() fileId: number; - @Output() back = new EventEmitter(); - public form: FormGroup; - public subscription: Subscription; - public fileTypes = [ - { value: FileType.None, text: null }, - { value: FileType.Sheet, text: 'Text' }, - { value: FileType.Chords, text: 'Text + Akkorde' }, - { value: FileType.MuseScore, text: 'MuseScore' } - ]; + @Input() fileId: number; + @Output() back = new EventEmitter(); + public form: FormGroup; + public subscription: Subscription; + public fileTypes = [ + {value: FileType.None, text: null}, + {value: FileType.Sheet, text: 'Text'}, + {value: FileType.Chords, text: 'Text + Akkorde'}, + {value: FileType.MuseScore, text: 'MuseScore'} + ]; - constructor( - private editSongService: EditSongService, - private songService: SongsService - ) {} + constructor( + private editSongService: EditSongService, + private songService: SongsService + ) { + } - public ngOnInit(): void { - const form = this.editSongService.initFileEditForm( - this.songService.selectedSong.value.ID, - this.fileId - ); - this.form = form.form; - this.subscription = form.changeSubscription; - } + public ngOnInit(): void { + const form = this.editSongService.initFileEditForm( + this.songService.selectedSong.value.ID, + this.fileId + ); + this.form = form.form; + this.subscription = form.changeSubscription; + } - public ngOnDestroy(): void { - this.form = null; - this.subscription.unsubscribe(); - } + public ngOnDestroy(): void { + this.form = null; + this.subscription.unsubscribe(); + } } diff --git a/WEB/src/app/components/songs/song-files/song-files.component.html b/WEB/src/app/components/songs/song-files/song-files.component.html index 680938e..747c550 100644 --- a/WEB/src/app/components/songs/song-files/song-files.component.html +++ b/WEB/src/app/components/songs/song-files/song-files.component.html @@ -1,90 +1,90 @@ -
- - - - - - - +
+ + +
- Angehängte Dateien - - {{ element.Name }} - -
+ + + + - - - - + + + + - - -
+ Angehängte Dateien + + {{ element.Name }} + + - - - - - - - - + + + + + + + +
-
-
+ + + + +
diff --git a/WEB/src/app/components/songs/song-files/song-files.component.less b/WEB/src/app/components/songs/song-files/song-files.component.less index 3c388ec..154d229 100644 --- a/WEB/src/app/components/songs/song-files/song-files.component.less +++ b/WEB/src/app/components/songs/song-files/song-files.component.less @@ -5,11 +5,12 @@ button { font-size: 24px; color: #aaa; + &:hover { color: #000; } } tr.file-over { - background: #f908; + background: #f908; } diff --git a/WEB/src/app/components/songs/song-files/song-files.component.ts b/WEB/src/app/components/songs/song-files/song-files.component.ts index 6f13897..4c6aa1b 100644 --- a/WEB/src/app/components/songs/song-files/song-files.component.ts +++ b/WEB/src/app/components/songs/song-files/song-files.component.ts @@ -1,74 +1,71 @@ -import { switchMap } from 'rxjs/operators'; -import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; -import { Song } from 'src/app/models/song.model'; -import { SongsService } from 'src/app/data/songs.service'; -import { DownloadService } from 'src/app/data/download.service'; -import { - faFileUpload, - faDownload, - faEdit, - faLongArrowAltLeft, - faTrash -} from '@fortawesome/free-solid-svg-icons'; -import { FileuploadFactory } from 'src/app/services/fileupload.factory'; -import { FileUploader } from 'ng2-file-upload'; +import {switchMap} from 'rxjs/operators'; +import {ChangeDetectorRef, Component} from '@angular/core'; +import {Song} from 'src/app/models/song.model'; +import {SongsService} from 'src/app/data/songs.service'; +import {DownloadService} from 'src/app/data/download.service'; +import {faDownload, faEdit, faFileUpload, faLongArrowAltLeft, faTrash} from '@fortawesome/free-solid-svg-icons'; +import {FileuploadFactory} from 'src/app/services/fileupload.factory'; +import {FileUploader} from 'ng2-file-upload'; @Component({ - selector: 'app-song-files', - templateUrl: './song-files.component.html', - styleUrls: ['./song-files.component.less'] + selector: 'app-song-files', + templateUrl: './song-files.component.html', + styleUrls: ['./song-files.component.less'] }) export class SongFilesComponent { - public song: Song; - public selectedSongId = 0; - public faFileUpload = faFileUpload; - public faTrash = faTrash; - public faArrow = faLongArrowAltLeft; - public faDownload = faDownload; - public faEdit = faEdit; - public columns = ['name', 'action']; - public newFileUploader: FileUploader; - public fileEditId: number; + public song: Song; + public selectedSongId = 0; + public faFileUpload = faFileUpload; + public faTrash = faTrash; + public faArrow = faLongArrowAltLeft; + public faDownload = faDownload; + public faEdit = faEdit; + public columns = ['name', 'action']; + public newFileUploader: FileUploader; + public fileEditId: number; - public fileOverNew = false; + public fileOverNew = false; - constructor( - private downloadService: DownloadService, - private fileuploadFactory: FileuploadFactory, - private songService: SongsService, - change: ChangeDetectorRef - ) { - songService.selectedSong.subscribe(_ => { - if (_) { - this.selectedSongId = _.ID; - this.song = _; - this.newFileUploader = this.fileuploadFactory.provideForNewFiles(_.ID); - this.newFileUploader.onCompleteItem = () => - songService.selectSong(_.ID).subscribe(); - this.newFileUploader.onProgressItem = () => change.markForCheck; - } else { - this.selectedSongId = 0; - this.song = null; - this.newFileUploader = null; - } - change.markForCheck(); - }); - } + constructor( + private downloadService: DownloadService, + private fileuploadFactory: FileuploadFactory, + private songService: SongsService, + change: ChangeDetectorRef + ) { + songService.selectedSong.subscribe(_ => { + if (_) { + this.selectedSongId = _.ID; + this.song = _; + this.newFileUploader = FileuploadFactory.provideForNewFiles(_.ID); + this.newFileUploader.onCompleteItem = () => + songService.selectSong(_.ID).subscribe(); + this.newFileUploader.onProgressItem = () => change.markForCheck; + } else { + this.selectedSongId = 0; + this.song = null; + this.newFileUploader = null; + } + change.markForCheck(); + }); + } - public onClickDownload(fileId: number, filename): void { - this.downloadService.get(this.selectedSongId, fileId, filename); - } - public onFileOverNew(hover: boolean): void { - this.fileOverNew = hover; - } - public onClickEdit(fileId: number): void { - this.fileEditId = fileId; - } - public onClickDelete(fileId: number): void { - const songId = this.song.ID; - this.songService - .deleteFile$(songId, fileId) - .pipe(switchMap(() => this.songService.selectSong(songId))) - .subscribe(); - } + public onClickDownload(fileId: number, filename): void { + this.downloadService.get(this.selectedSongId, fileId, filename); + } + + public onFileOverNew(hover: boolean): void { + this.fileOverNew = hover; + } + + public onClickEdit(fileId: number): void { + this.fileEditId = fileId; + } + + public onClickDelete(fileId: number): void { + const songId = this.song.ID; + this.songService + .deleteFile$(songId, fileId) + .pipe(switchMap(() => this.songService.selectSong(songId))) + .subscribe(); + } } diff --git a/WEB/src/app/components/songs/song-form/keys.ts b/WEB/src/app/components/songs/song-form/keys.ts index c091288..3998261 100644 --- a/WEB/src/app/components/songs/song-form/keys.ts +++ b/WEB/src/app/components/songs/song-form/keys.ts @@ -33,4 +33,4 @@ export const keys = [ 'A#', 'b', 'h' - ]; \ No newline at end of file +]; diff --git a/WEB/src/app/components/songs/song-form/song-form.component.html b/WEB/src/app/components/songs/song-form/song-form.component.html index ed8c1f2..4ac7d35 100644 --- a/WEB/src/app/components/songs/song-form/song-form.component.html +++ b/WEB/src/app/components/songs/song-form/song-form.component.html @@ -1,53 +1,53 @@
- +
- - Lobpreis - Anbetung - - - - - - Tonart - - - {{ key }} - - - - - - + + Lobpreis + Anbetung + + + + + + Tonart + + + {{ key }} + + + + + +
- -
\ No newline at end of file + + diff --git a/WEB/src/app/components/songs/song-form/song-form.component.less b/WEB/src/app/components/songs/song-form/song-form.component.less index 572538b..17f1e31 100644 --- a/WEB/src/app/components/songs/song-form/song-form.component.less +++ b/WEB/src/app/components/songs/song-form/song-form.component.less @@ -1,9 +1,10 @@ form { - display: flex; - flex-direction: column; - .row { - display: grid; - grid-template-columns: 3fr 1fr 1fr 1fr; - grid-column-gap: 20px; - } + display: flex; + flex-direction: column; + + .row { + display: grid; + grid-template-columns: 3fr 1fr 1fr 1fr; + grid-column-gap: 20px; + } } diff --git a/WEB/src/app/components/songs/song-form/song-form.component.ts b/WEB/src/app/components/songs/song-form/song-form.component.ts index 3374c66..8362db8 100644 --- a/WEB/src/app/components/songs/song-form/song-form.component.ts +++ b/WEB/src/app/components/songs/song-form/song-form.component.ts @@ -1,13 +1,13 @@ -import { FormGroup } from '@angular/forms'; -import { Component, Input } from '@angular/core'; -import { keys } from './keys'; +import {FormGroup} from '@angular/forms'; +import {Component, Input} from '@angular/core'; +import {keys} from './keys'; @Component({ - selector: 'app-song-form', - templateUrl: './song-form.component.html', - styleUrls: ['./song-form.component.less'] + selector: 'app-song-form', + templateUrl: './song-form.component.html', + styleUrls: ['./song-form.component.less'] }) -export class SongFormComponent { - @Input() public form: FormGroup; - public keys = keys; +export class SongFormComponent { + @Input() public form: FormGroup; + public keys = keys; } diff --git a/WEB/src/app/components/songs/song-new/song-new.component.html b/WEB/src/app/components/songs/song-new/song-new.component.html index e40b680..5991e21 100644 --- a/WEB/src/app/components/songs/song-new/song-new.component.html +++ b/WEB/src/app/components/songs/song-new/song-new.component.html @@ -1,22 +1,23 @@
- - -
- -
- Neuen Titel anlegen - - -
- - - - - - + + +
+ +
+ Neuen Titel anlegen + + +
+ + + + + +
-
+ diff --git a/WEB/src/app/components/songs/song-new/song-new.component.ts b/WEB/src/app/components/songs/song-new/song-new.component.ts index c19dee2..43f402a 100644 --- a/WEB/src/app/components/songs/song-new/song-new.component.ts +++ b/WEB/src/app/components/songs/song-new/song-new.component.ts @@ -1,39 +1,40 @@ -import { EditSongService } from './../../../data/edit-song.service'; -import { FormGroup } from '@angular/forms'; -import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; -import { faLongArrowAltLeft, faSave } from '@fortawesome/free-solid-svg-icons'; -import { State } from 'src/app/data/state'; -import { SongsService } from 'src/app/data/songs.service'; +import {EditSongService} from '../../../data/edit-song.service'; +import {FormGroup} from '@angular/forms'; +import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit} from '@angular/core'; +import {faLongArrowAltLeft, faSave} from '@fortawesome/free-solid-svg-icons'; +import {State} from 'src/app/data/state'; +import {SongsService} from 'src/app/data/songs.service'; @Component({ - selector: 'app-song-new', - templateUrl: './song-new.component.html', - styleUrls: ['./song-new.component.less'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'app-song-new', + templateUrl: './song-new.component.html', + styleUrls: ['./song-new.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush }) export class SongNewComponent implements OnInit { - public faArrow = faLongArrowAltLeft; - public faSave = faSave; - public form: FormGroup; + public faArrow = faLongArrowAltLeft; + public faSave = faSave; + public form: FormGroup; - constructor( - private editSongService: EditSongService, - private songsService: SongsService, - private change: ChangeDetectorRef - ) { } + constructor( + private editSongService: EditSongService, + private songsService: SongsService, + private change: ChangeDetectorRef + ) { + } - ngOnInit() { - this.form = this.editSongService.initSongEditForm(false); - this.change.markForCheck(); - } + ngOnInit() { + this.form = this.editSongService.initSongEditForm(false); + this.change.markForCheck(); + } - public onBack(): void { - this.songsService.state = State.list; - this.songsService.resetSelectedSong(); - } + public onBack(): void { + this.songsService.state = State.list; + this.songsService.resetSelectedSong(); + } - public onClickAdd(): void { - this.songsService.saveNewSong$(this.form.value).subscribe(); - } + public onClickAdd(): void { + this.songsService.saveNewSong$(this.form.value).subscribe(); + } } diff --git a/WEB/src/app/components/songs/song/song.component.html b/WEB/src/app/components/songs/song/song.component.html index 05f254c..a26295f 100644 --- a/WEB/src/app/components/songs/song/song.component.html +++ b/WEB/src/app/components/songs/song/song.component.html @@ -1,29 +1,32 @@ -
- - -
- -
- {{ song.Name }} - - - {{ renderSongType(song.SongType).name }} - Tonart: {{ song.Key }} - Tempo: {{ song.Tempo }} - -
- -

{{ line }}

-
-

{{ line }}

-
- - - -
+
+ + +
+ +
+ {{ song.Name }} + + + {{ renderSongType(song.SongType).name }} + Tonart: {{ song.Key }} + Tempo: {{ song.Tempo }} + + +
+ +

{{ line }}

+
+

{{ line }}

+
+ + + +
diff --git a/WEB/src/app/components/songs/song/song.component.ts b/WEB/src/app/components/songs/song/song.component.ts index f153a55..edc2074 100644 --- a/WEB/src/app/components/songs/song/song.component.ts +++ b/WEB/src/app/components/songs/song/song.component.ts @@ -1,62 +1,61 @@ -import { SongsService } from 'src/app/data/songs.service'; -import { - Component, - ChangeDetectionStrategy, - ChangeDetectorRef -} from '@angular/core'; -import { faLongArrowAltLeft, faEdit } from '@fortawesome/free-solid-svg-icons'; -import { Song } from 'src/app/models/song.model'; -import { DownloadService } from 'src/app/data/download.service'; -import { State } from 'src/app/data/state'; +import {SongsService} from 'src/app/data/songs.service'; +import {ChangeDetectionStrategy, ChangeDetectorRef, Component} from '@angular/core'; +import {faEdit, faLongArrowAltLeft} from '@fortawesome/free-solid-svg-icons'; +import {Song} from 'src/app/models/song.model'; +import {State} from 'src/app/data/state'; @Component({ - selector: 'app-song', - templateUrl: './song.component.html', - styleUrls: ['./song.component.less'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'app-song', + templateUrl: './song.component.html', + styleUrls: ['./song.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush }) export class SongComponent { - public song: Song; - public faArrow = faLongArrowAltLeft; - public faEdit = faEdit; - public selectedSongId = 0; + public song: Song; + public faArrow = faLongArrowAltLeft; + public faEdit = faEdit; + public selectedSongId = 0; - constructor( - private songService: SongsService, - change: ChangeDetectorRef - ) { - songService.selectedSong.subscribe(_ => { - if (_) { - this.selectedSongId = _.ID; - this.song = _; - } else { - this.selectedSongId = 0; - this.song = null; - } - change.markForCheck(); - }); - } - public onBack(): void { - this.songService.resetSelectedSong(); - } - - public onClickEdit(): void { - this.songService.state = State.edit; - } - - public get text(): string[] { - return this.song && this.song.Text ? this.song.Text.split(/\r?\n/) : []; - } - - public get comments(): string[] { - return this.song && this.song.Comments ? this.song.Comments.split(/\r?\n/) : []; - } - - public renderSongType(songType: string) { - switch (songType) { - case 'Praise': return {name: 'Lobpreis', color: '#99FFB8'}; - case 'Worship': return {name: 'Anbetung', color: '#C999FF'}; - default: return null; + constructor( + private songService: SongsService, + change: ChangeDetectorRef + ) { + songService.selectedSong.subscribe(_ => { + if (_) { + this.selectedSongId = _.ID; + this.song = _; + } else { + this.selectedSongId = 0; + this.song = null; + } + change.markForCheck(); + }); + } + + public get text(): string[] { + return this.song && this.song.Text ? this.song.Text.split(/\r?\n/) : []; + } + + public get comments(): string[] { + return this.song && this.song.Comments ? this.song.Comments.split(/\r?\n/) : []; + } + + public onBack(): void { + this.songService.resetSelectedSong(); + } + + public onClickEdit(): void { + this.songService.state = State.edit; + } + + public renderSongType(songType: string) { + switch (songType) { + case 'Praise': + return {name: 'Lobpreis', color: '#99FFB8'}; + case 'Worship': + return {name: 'Anbetung', color: '#C999FF'}; + default: + return null; + } } - } } diff --git a/WEB/src/app/components/songs/songs.component.html b/WEB/src/app/components/songs/songs.component.html index 02059cb..fc668b7 100644 --- a/WEB/src/app/components/songs/songs.component.html +++ b/WEB/src/app/components/songs/songs.component.html @@ -1,5 +1,5 @@ - - - - + + + + diff --git a/WEB/src/app/components/songs/songs.component.ts b/WEB/src/app/components/songs/songs.component.ts index b786264..ac3e697 100644 --- a/WEB/src/app/components/songs/songs.component.ts +++ b/WEB/src/app/components/songs/songs.component.ts @@ -1,17 +1,18 @@ -import { blend } from 'src/app/services/animation'; -import { Component } from '@angular/core'; -import { SongsService } from 'src/app/data/songs.service'; -import { State } from 'src/app/data/state'; +import {blend} from 'src/app/services/animation'; +import {Component} from '@angular/core'; +import {SongsService} from 'src/app/data/songs.service'; +import {State} from 'src/app/data/state'; @Component({ - selector: 'app-songs', - templateUrl: './songs.component.html', - styleUrls: ['./songs.component.less'], - animations: [blend] + selector: 'app-songs', + templateUrl: './songs.component.html', + styleUrls: ['./songs.component.less'], + animations: [blend] }) export class SongsComponent { - public State = State; - constructor(public songsService: SongsService) { - songsService.loadSongList$().subscribe(); - } + public State = State; + + constructor(public songsService: SongsService) { + songsService.loadSongList$().subscribe(); + } } diff --git a/WEB/src/app/components/songs/table/table.component.html b/WEB/src/app/components/songs/table/table.component.html index e81849e..59b414a 100644 --- a/WEB/src/app/components/songs/table/table.component.html +++ b/WEB/src/app/components/songs/table/table.component.html @@ -1,75 +1,75 @@
-
- - - - - - +
+ +
# - - {{ element.Number }} - -
+ + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - -
# + + {{ element.Number }} + + Titel{{ element.Name }}Titel{{ element.Name }} - - {{ element.Key }} - - + + {{ element.Key }} + + - - {{ renderSongType(element.SongType).name }} - - + + {{ renderSongType(element.SongType).name }} + + - - {{ element.Tempo }} - - + + {{ element.Tempo }} + +
-
+ + + +
diff --git a/WEB/src/app/components/songs/table/table.component.less b/WEB/src/app/components/songs/table/table.component.less index 9b669f4..6054036 100644 --- a/WEB/src/app/components/songs/table/table.component.less +++ b/WEB/src/app/components/songs/table/table.component.less @@ -17,6 +17,7 @@ table { font-size: 24px; z-index: 1000; color: #aaa; + &:hover { color: #000; } diff --git a/WEB/src/app/components/songs/table/table.component.ts b/WEB/src/app/components/songs/table/table.component.ts index 2782b6b..435f06d 100644 --- a/WEB/src/app/components/songs/table/table.component.ts +++ b/WEB/src/app/components/songs/table/table.component.ts @@ -1,56 +1,56 @@ -import { SongsService } from './../../../data/songs.service'; -import { - Component, - ChangeDetectionStrategy, - ChangeDetectorRef -} from '@angular/core'; -import { State } from 'src/app/data/state'; -import { faFileMedical } from '@fortawesome/free-solid-svg-icons'; +import {SongsService} from '../../../data/songs.service'; +import {ChangeDetectionStrategy, ChangeDetectorRef, Component} from '@angular/core'; +import {State} from 'src/app/data/state'; +import {faFileMedical} from '@fortawesome/free-solid-svg-icons'; @Component({ - selector: 'app-table', - templateUrl: './table.component.html', - styleUrls: ['./table.component.less'], - changeDetection: ChangeDetectionStrategy.OnPush + selector: 'app-table', + templateUrl: './table.component.html', + styleUrls: ['./table.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush }) export class TableComponent { - public selectedSongId = 0; - public State = State; - public faNew = faFileMedical; - public columnsFull = ['Number', 'Name', 'Key', 'SongType', 'Tempo']; - public columnsPinned = ['Number', 'Name']; - public get columns(): string[] { - return this.songsService.state === State.list ? this.columnsFull : this.columnsPinned; - } + public selectedSongId = 0; + public State = State; + public faNew = faFileMedical; + public columnsFull = ['Number', 'Name', 'Key', 'SongType', 'Tempo']; + public columnsPinned = ['Number', 'Name']; - constructor( - public songsService: SongsService, - private change: ChangeDetectorRef - ) { - songsService.selectedSong.subscribe(_ => { - this.selectedSongId = _ ? _.ID : 0; - this.change.markForCheck(); - } - ); - } - - public renderSongType(songType: string) { - switch (songType) { - case 'Praise': return {name: 'Lobpreis', color: '#99FFB8'}; - case 'Worship': return {name: 'Anbetung', color: '#C999FF'}; - default: return null; + constructor( + public songsService: SongsService, + private change: ChangeDetectorRef + ) { + songsService.selectedSong.subscribe(_ => { + this.selectedSongId = _ ? _.ID : 0; + this.change.markForCheck(); + } + ); } - } - public onClick(id: number): void { - this.songsService.selectSong(id).subscribe(); - this.change.detectChanges(); - } + public get columns(): string[] { + return this.songsService.state === State.list ? this.columnsFull : this.columnsPinned; + } - public onClickNew(): void { - this.songsService.selectSong(null).subscribe(); - this.songsService.state = State.new; - this.change.detectChanges(); - } + public renderSongType(songType: string) { + switch (songType) { + case 'Praise': + return {name: 'Lobpreis', color: '#99FFB8'}; + case 'Worship': + return {name: 'Anbetung', color: '#C999FF'}; + default: + return null; + } + } + + public onClick(id: number): void { + this.songsService.selectSong(id).subscribe(); + this.change.detectChanges(); + } + + public onClickNew(): void { + this.songsService.selectSong(null).subscribe(); + this.songsService.state = State.new; + this.change.detectChanges(); + } } diff --git a/WEB/src/app/data/download.service.ts b/WEB/src/app/data/download.service.ts index b4178fb..9b2c185 100644 --- a/WEB/src/app/data/download.service.ts +++ b/WEB/src/app/data/download.service.ts @@ -1,32 +1,33 @@ -import { base } from './urls'; -import { HttpClient } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import {base} from './urls'; +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; @Injectable({ - providedIn: 'root' + providedIn: 'root' }) export class DownloadService { - constructor(private httpClient: HttpClient) {} + constructor(private httpClient: HttpClient) { + } - public get(songId: number, fileId: number, filename: string) { - return this.httpClient - .get(base + '/api/songs/' + songId + '/files/' + fileId, { - responseType: 'blob' as 'json', - observe: 'response' - }) - .subscribe( - (response: any) => { - const contentType = response.headers.get('Content-Type'); - const downloadLink = document.createElement('a'); - const blob = new Blob([response.body], { type: contentType }); - downloadLink.href = window.URL.createObjectURL(blob); - downloadLink.setAttribute('download', filename); - document.body.appendChild(downloadLink); - downloadLink.click(); - }, - error => { - console.log('download error:', JSON.stringify(error)); - } - ); - } + public get(songId: number, fileId: number, filename: string) { + return this.httpClient + .get(base + '/api/songs/' + songId + '/files/' + fileId, { + responseType: 'blob' as 'json', + observe: 'response' + }) + .subscribe( + (response: any) => { + const contentType = response.headers.get('Content-Type'); + const downloadLink = document.createElement('a'); + const blob = new Blob([response.body], {type: contentType}); + downloadLink.href = window.URL.createObjectURL(blob); + downloadLink.setAttribute('download', filename); + document.body.appendChild(downloadLink); + downloadLink.click(); + }, + error => { + console.log('download error:', JSON.stringify(error)); + } + ); + } } diff --git a/WEB/src/app/data/edit-song.service.ts b/WEB/src/app/data/edit-song.service.ts index 7916d98..d1a9d0f 100644 --- a/WEB/src/app/data/edit-song.service.ts +++ b/WEB/src/app/data/edit-song.service.ts @@ -1,105 +1,106 @@ -import { FileType } from './../models/files-types.model.ts'; -import { SongsService } from 'src/app/data/songs.service'; -import { Injectable } from '@angular/core'; -import { FormGroup, FormControl, Validators } from '@angular/forms'; -import { switchMap } from 'rxjs/operators'; -import { Song } from '../models/song.model'; -import { Subscription } from 'rxjs'; +import {SongsService} from 'src/app/data/songs.service'; +import {Injectable} from '@angular/core'; +import {FormControl, FormGroup, Validators} from '@angular/forms'; +import {switchMap} from 'rxjs/operators'; +import {Song} from '../models/song.model'; +import {Subscription} from 'rxjs'; @Injectable({ - providedIn: 'root' + providedIn: 'root' }) export class EditSongService { - constructor(private songsService: SongsService) {} - - public initSongEditForm(attachSync: boolean): FormGroup { - const song = attachSync - ? this.songsService.selectedSong.value - : this.defaultValues(); - const form = new FormGroup({ - Number: new FormControl(song.Number, { - updateOn: 'blur', - validators: [Validators.required, Validators.min(1)] - }), - Name: new FormControl(song.Name, { - updateOn: 'blur', - validators: Validators.required - }), - Text: new FormControl(song.Text, { updateOn: 'blur' }), - SongType: new FormControl(song.SongType, { - updateOn: 'blur', - validators: Validators.required - }), - Key: new FormControl(song.Key, { - updateOn: 'blur', - validators: Validators.required - }), - Tempo: new FormControl(song.Tempo, { updateOn: 'blur' }), - Comments: new FormControl(song.Comments, { updateOn: 'blur' }) - }); - - if (attachSync) { - this.attachSync(form, song); + constructor(private songsService: SongsService) { } - return form; - } + public initSongEditForm(attachSync: boolean): FormGroup { + const song = attachSync + ? this.songsService.selectedSong.value + : this.defaultValues(); + const form = new FormGroup({ + Number: new FormControl(song.Number, { + updateOn: 'blur', + validators: [Validators.required, Validators.min(1)] + }), + Name: new FormControl(song.Name, { + updateOn: 'blur', + validators: Validators.required + }), + Text: new FormControl(song.Text, {updateOn: 'blur'}), + SongType: new FormControl(song.SongType, { + updateOn: 'blur', + validators: Validators.required + }), + Key: new FormControl(song.Key, { + updateOn: 'blur', + validators: Validators.required + }), + Tempo: new FormControl(song.Tempo, {updateOn: 'blur'}), + Comments: new FormControl(song.Comments, {updateOn: 'blur'}) + }); - public initFileEditForm(songId: number, fileId: number): {form: FormGroup, changeSubscription: Subscription } { - const file = this.songsService.selectedSong.value.Files.filter( - _ => _.ID === fileId - )[0]; - const form = new FormGroup({ - Name: new FormControl(file.Name, { - updateOn: 'blur', - validators: Validators.required - }), - FileType: new FormControl(file.FileType, { - updateOn: 'blur' - }) - }); + if (attachSync) { + this.attachSync(form, song); + } - const changeSubscription = form.valueChanges.pipe( - switchMap(_ => this.songsService.updateFile$(songId, fileId, _.Name, _.FileType)), - switchMap(() => this.songsService.selectSong(songId)) - ).subscribe(); + return form; + } - return {form : form, changeSubscription: changeSubscription}; - } + public initFileEditForm(songId: number, fileId: number): { form: FormGroup, changeSubscription: Subscription } { + const file = this.songsService.selectedSong.value.Files.filter( + _ => _.ID === fileId + )[0]; + const form = new FormGroup({ + Name: new FormControl(file.Name, { + updateOn: 'blur', + validators: Validators.required + }), + FileType: new FormControl(file.FileType, { + updateOn: 'blur' + }) + }); - private attachSync(form: FormGroup, song: Song) { - const controls = Object.keys(form.controls); - controls.forEach(control => { - form.controls[control].valueChanges - .pipe( - switchMap(value => this.songsService.patch$(song.ID, control, value)), - switchMap(() => this.songsService.selectSong(song.ID)) - ) - .subscribe(); - }); - } + const changeSubscription = form.valueChanges.pipe( + switchMap(_ => this.songsService.updateFile$(songId, fileId, _.Name, _.FileType)), + switchMap(() => this.songsService.selectSong(songId)) + ).subscribe(); - private defaultValues(): Song { - const song: Song = { - ID: null, - Number: this.firstFreeNumber(), - Name: null, - Tempo: null, - Text: null, - SongType: null, - Key: null, - Comments: null, - Final: false, - Files: [] - }; + return {form: form, changeSubscription: changeSubscription}; + } - return song; - } + private attachSync(form: FormGroup, song: Song) { + const controls = Object.keys(form.controls); + controls.forEach(control => { + form.controls[control].valueChanges + .pipe( + switchMap(value => this.songsService.patch$(song.ID, control, value)), + switchMap(() => this.songsService.selectSong(song.ID)) + ) + .subscribe(); + }); + } - private firstFreeNumber(): number { - let number = 0; - const numbers = this.songsService.songs.value.map(_ => _.Number); - while (numbers.indexOf(++number) !== -1) {} - return number; - } + private defaultValues(): Song { + const song: Song = { + ID: null, + Number: this.firstFreeNumber(), + Name: null, + Tempo: null, + Text: null, + SongType: null, + Key: null, + Comments: null, + Final: false, + Files: [] + }; + + return song; + } + + private firstFreeNumber(): number { + let number = 0; + const numbers = this.songsService.songs.value.map(_ => _.Number); + while (numbers.indexOf(++number) !== -1) { + } + return number; + } } diff --git a/WEB/src/app/data/odata.service.ts b/WEB/src/app/data/odata.service.ts index 8cd27de..72a8b6f 100644 --- a/WEB/src/app/data/odata.service.ts +++ b/WEB/src/app/data/odata.service.ts @@ -1,63 +1,63 @@ -import { Song } from 'src/app/models/song.model'; -import { ODataService, ODataQuery, Expand } from 'odata-v4-ng'; -import { Observable } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; -import { base } from './urls'; +import {Expand, ODataQuery, ODataService} from 'odata-v4-ng'; +import {Observable} from 'rxjs'; +import {map, tap} from 'rxjs/operators'; +import {base} from './urls'; export class OdataService { - private url: string; - constructor(private odataService: ODataService, private entity: string) { - this.url = base + '/odata/'; - } + private url: string; - public list$(properties: string[]): Observable { - const query = new ODataQuery(this.odataService, this.url) - .entitySet(this.entity) - .select(properties); - const get = query.get().pipe(map(_ => _.toPropertyValue())); + constructor(private odataService: ODataService, private entity: string) { + this.url = base + '/odata/'; + } - return get; - } + public list$(properties: string[]): Observable { + const query = new ODataQuery(this.odataService, this.url) + .entitySet(this.entity) + .select(properties); + const get = query.get().pipe(map(_ => _.toPropertyValue())); - public get$( - id: number, - properties: string[], - expands: string[] - ): Observable { - const query = new ODataQuery(this.odataService, this.url) - .entitySet(this.entity) - .entityKey(id) - .expand(expands.map(_ => new Expand(_))) - .select(properties); - const get = query.get().pipe(map(_ => _.toEntity())); + return get; + } - return get; - } + public get$( + id: number, + properties: string[], + expands: string[] + ): Observable { + const query = new ODataQuery(this.odataService, this.url) + .entitySet(this.entity) + .entityKey(id) + .expand(expands.map(_ => new Expand(_))) + .select(properties); + const get = query.get().pipe(map(_ => _.toEntity())); - public patch$(id: number, control: string, value: any): Observable { - const valueSet = { [control]: value }; - const query = new ODataQuery(this.odataService, this.url) - .entitySet(this.entity) - .entityKey(id); - const get = query.patch(valueSet).pipe(map(() => true)); + return get; + } - return get; - } + public patch$(id: number, control: string, value: any): Observable { + const valueSet = {[control]: value}; + const query = new ODataQuery(this.odataService, this.url) + .entitySet(this.entity) + .entityKey(id); + const get = query.patch(valueSet).pipe(map(() => true)); - public post$(values: any): Observable { - const querry = new ODataQuery(this.odataService, this.url); - const post = querry - .entitySet(this.entity) - .post(values) - .pipe( - tap(_ => console.log(_)), - map(_ => { - const mapped = _.toEntity(); - return mapped; - }), - tap(_ => console.log(_)) - ); + return get; + } - return post; - } + public post$(values: any): Observable { + const querry = new ODataQuery(this.odataService, this.url); + const post = querry + .entitySet(this.entity) + .post(values) + .pipe( + tap(_ => console.log(_)), + map(_ => { + const mapped = _.toEntity(); + return mapped; + }), + tap(_ => console.log(_)) + ); + + return post; + } } diff --git a/WEB/src/app/data/songs.service.ts b/WEB/src/app/data/songs.service.ts index cb6e2bc..2015df5 100644 --- a/WEB/src/app/data/songs.service.ts +++ b/WEB/src/app/data/songs.service.ts @@ -1,124 +1,124 @@ -import { HttpClient } from '@angular/common/http'; -import { FileType } from './../models/files-types.model.ts'; -import { Injectable } from '@angular/core'; -import { ODataService } from 'odata-v4-ng'; -import { OdataService } from './odata.service'; -import { Song } from '../models/song.model'; -import { BehaviorSubject, Observable } from 'rxjs'; -import { tap, switchMap } from 'rxjs/operators'; -import { State } from './state'; -import { base } from './urls'; +import {HttpClient} from '@angular/common/http'; +import {FileType} from './../models/files-types.model.ts'; +import {Injectable} from '@angular/core'; +import {ODataService} from 'odata-v4-ng'; +import {OdataService} from './odata.service'; +import {Song} from '../models/song.model'; +import {BehaviorSubject, Observable} from 'rxjs'; +import {switchMap, tap} from 'rxjs/operators'; +import {State} from './state'; +import {base} from './urls'; @Injectable({ - providedIn: 'root' + providedIn: 'root' }) export class SongsService extends OdataService { - public state = State.list; + public state = State.list; - public songs: BehaviorSubject = new BehaviorSubject([]); - public selectedSong: BehaviorSubject = new BehaviorSubject(null); + public songs: BehaviorSubject = new BehaviorSubject([]); + public selectedSong: BehaviorSubject = new BehaviorSubject(null); - constructor(odataService: ODataService, private httpClient: HttpClient) { - super(odataService, 'songs'); - } - - public loadSongList$(): Observable { - const properties = ['ID', 'Name', 'Number', 'SongType', 'Key', 'Tempo']; - const list = this.list$(properties).pipe( - tap(_ => this.songs.next(_)) - ); - return list; - } - - public loadSongListAndGoTo$(id: number): Observable { - const properties = ['ID', 'Name', 'Number', 'SongType', 'Key', 'Tempo']; - const list = this.list$(properties).pipe( - tap(_ => { - this.songs.next(_); - }), - switchMap(() => this.selectSong(id)) - ); - - return list; - } - - public selectSong(id: number): Observable { - this.state = State.read; - const filter = this.songs.value.filter(_ => _.ID === id); - const song = filter.length === 1 ? filter[0] : null; - if (!song) { - return; + constructor(odataService: ODataService, private httpClient: HttpClient) { + super(odataService, 'songs'); } - const get = this.get$(id, ['Text', 'Comments'], ['Files']).pipe(tap(_ => { - song.Text = _.Text; - song.Comments = _.Comments; - song.Files = _.Files; - this.selectedSong.next(song); - })); + public loadSongList$(): Observable { + const properties = ['ID', 'Name', 'Number', 'SongType', 'Key', 'Tempo']; + const list = this.list$(properties).pipe( + tap(_ => this.songs.next(_)) + ); + return list; + } - return get; - } + public loadSongListAndGoTo$(id: number): Observable { + const properties = ['ID', 'Name', 'Number', 'SongType', 'Key', 'Tempo']; + const list = this.list$(properties).pipe( + tap(_ => { + this.songs.next(_); + }), + switchMap(() => this.selectSong(id)) + ); - public resetSelectedSong() { - this.state = State.list; - this.selectedSong.next(null); - } + return list; + } - public patch$(id: number, control: string, value: any): Observable { - const patch = super.patch$(id, control, value).pipe( - tap(() => { - const songs = this.songs.value; - const song = songs.filter(_ => _.ID === id)[0]; - song[control] = value; - this.songs.next(songs); - this.selectedSong.next(song); - }) - ); + public selectSong(id: number): Observable { + this.state = State.read; + const filter = this.songs.value.filter(_ => _.ID === id); + const song = filter.length === 1 ? filter[0] : null; + if (!song) { + return; + } - return patch; - } + const get = this.get$(id, ['Text', 'Comments'], ['Files']).pipe(tap(_ => { + song.Text = _.Text; + song.Comments = _.Comments; + song.Files = _.Files; + this.selectedSong.next(song); + })); - public saveNewSong$(values: any): Observable { - const newSong = super - .post$(values) - .pipe(switchMap(_ => this.loadSongListAndGoTo$(_.ID))); + return get; + } - return newSong; - } + public resetSelectedSong() { + this.state = State.list; + this.selectedSong.next(null); + } - public updateFile$( - songId: number, - fileId: number, - name: string, - fileType: FileType - ): Observable { - const url = - base + - '/api/songs/' + - songId + - '/files/' + - fileId + - '/edit?Name=' + - name + - '&FileType=' + - fileType; - const get = this.httpClient.get(url); - return get; - } + public patch$(id: number, control: string, value: any): Observable { + const patch = super.patch$(id, control, value).pipe( + tap(() => { + const songs = this.songs.value; + const song = songs.filter(_ => _.ID === id)[0]; + song[control] = value; + this.songs.next(songs); + this.selectedSong.next(song); + }) + ); - public deleteFile$( - songId: number, - fileId: number - ): Observable { - const url = - base + - '/api/songs/' + - songId + - '/files/' + - fileId + - '/delete'; - const get = this.httpClient.get(url); - return get; - } + return patch; + } + + public saveNewSong$(values: any): Observable { + const newSong = super + .post$(values) + .pipe(switchMap(_ => this.loadSongListAndGoTo$(_.ID))); + + return newSong; + } + + public updateFile$( + songId: number, + fileId: number, + name: string, + fileType: FileType + ): Observable { + const url = + base + + '/api/songs/' + + songId + + '/files/' + + fileId + + '/edit?Name=' + + name + + '&FileType=' + + fileType; + const get = this.httpClient.get(url); + return get; + } + + public deleteFile$( + songId: number, + fileId: number + ): Observable { + const url = + base + + '/api/songs/' + + songId + + '/files/' + + fileId + + '/delete'; + const get = this.httpClient.get(url); + return get; + } } diff --git a/WEB/src/app/data/state.ts b/WEB/src/app/data/state.ts index 4f9f653..adfb8f5 100644 --- a/WEB/src/app/data/state.ts +++ b/WEB/src/app/data/state.ts @@ -1,6 +1,6 @@ export enum State { - read, - edit, - new, - list + read, + edit, + new, + list } diff --git a/WEB/src/app/models/file.model.ts b/WEB/src/app/models/file.model.ts index 24076d7..8283ebd 100644 --- a/WEB/src/app/models/file.model.ts +++ b/WEB/src/app/models/file.model.ts @@ -1,6 +1,7 @@ -import { FileType } from './files-types.model.ts'; +import {FileType} from './files-types.model.ts'; + export interface File { - ID: number; - Name: string; - FileType: FileType; + ID: number; + Name: string; + FileType: FileType; } diff --git a/WEB/src/app/models/files-types.model.ts.ts b/WEB/src/app/models/files-types.model.ts.ts index 5f6ba36..c1f2c7d 100644 --- a/WEB/src/app/models/files-types.model.ts.ts +++ b/WEB/src/app/models/files-types.model.ts.ts @@ -1,6 +1,6 @@ export enum FileType { - None = 'None', - Sheet = 'Sheet', - Chords = 'Chords', - MuseScore = 'MuseScore' + None = 'None', + Sheet = 'Sheet', + Chords = 'Chords', + MuseScore = 'MuseScore' } diff --git a/WEB/src/app/models/song.model.ts b/WEB/src/app/models/song.model.ts index c64deee..b3acaa4 100644 --- a/WEB/src/app/models/song.model.ts +++ b/WEB/src/app/models/song.model.ts @@ -1,14 +1,14 @@ -import { File } from './file.model'; +import {File} from './file.model'; export interface Song { - ID: number; - Number: number; - Name: string; - Text: string; - Comments: string; - Key: string; - Tempo: number; - SongType: string; - Final: boolean; - Files: File[]; + ID: number; + Number: number; + Name: string; + Text: string; + Comments: string; + Key: string; + Tempo: number; + SongType: string; + Final: boolean; + Files: File[]; } diff --git a/WEB/src/app/services/animation.ts b/WEB/src/app/services/animation.ts index 9001239..fbbbf28 100644 --- a/WEB/src/app/services/animation.ts +++ b/WEB/src/app/services/animation.ts @@ -1,13 +1,13 @@ -import { trigger, transition, style, animate } from '@angular/animations'; +import {animate, style, transition, trigger} from '@angular/animations'; export const blend = trigger('blend', [ transition(':enter', [ - style({ opacity: 0, display: 'none' }), - animate('400ms', style({ opacity: 0 , display: 'none'})), - animate('300ms', style({ opacity: 1, display: 'block' })) + style({opacity: 0, display: 'none'}), + animate('400ms', style({opacity: 0, display: 'none'})), + animate('300ms', style({opacity: 1, display: 'block'})) ]), transition(':leave', [ - style({ opacity: 1, display: 'block' }), - animate('300ms', style({ opacity: 0, display: 'none' })) + style({opacity: 1, display: 'block'}), + animate('300ms', style({opacity: 0, display: 'none'})) ]) - ]); +]); diff --git a/WEB/src/app/services/fileupload.factory.ts b/WEB/src/app/services/fileupload.factory.ts index f542053..b6f94a5 100644 --- a/WEB/src/app/services/fileupload.factory.ts +++ b/WEB/src/app/services/fileupload.factory.ts @@ -1,18 +1,18 @@ -import { base } from './../data/urls'; -import { Injectable } from '@angular/core'; -import { FileUploader } from 'ng2-file-upload'; +import {base} from '../data/urls'; +import {Injectable} from '@angular/core'; +import {FileUploader} from 'ng2-file-upload'; @Injectable({ - providedIn: 'root' + providedIn: 'root' }) export class FileuploadFactory { - public provideForNewFiles(songId: number): FileUploader { - const uploader = new FileUploader({ - url: base + '/api/songs/' + songId + '/files', - autoUpload: true, - isHTML5: true - }); + public static provideForNewFiles(songId: number): FileUploader { + const uploader = new FileUploader({ + url: base + '/api/songs/' + songId + '/files', + autoUpload: true, + isHTML5: true + }); - return uploader; - } + return uploader; + } } diff --git a/WEB/src/environments/environment.prod.ts b/WEB/src/environments/environment.prod.ts index 3612073..5d08331 100644 --- a/WEB/src/environments/environment.prod.ts +++ b/WEB/src/environments/environment.prod.ts @@ -1,3 +1,3 @@ export const environment = { - production: true + production: true }; diff --git a/WEB/src/environments/environment.ts b/WEB/src/environments/environment.ts index 7b4f817..6b32308 100644 --- a/WEB/src/environments/environment.ts +++ b/WEB/src/environments/environment.ts @@ -3,7 +3,7 @@ // The list of file replacements can be found in `angular.json`. export const environment = { - production: false + production: false }; /* diff --git a/WEB/src/index.html b/WEB/src/index.html index a36cc6e..bf7ce82 100644 --- a/WEB/src/index.html +++ b/WEB/src/index.html @@ -1,14 +1,14 @@ - - Wgenerator - + + Wgenerator + - - + + - + diff --git a/WEB/src/karma.conf.js b/WEB/src/karma.conf.js index b6e0042..c1b01ff 100644 --- a/WEB/src/karma.conf.js +++ b/WEB/src/karma.conf.js @@ -2,30 +2,30 @@ // https://karma-runner.github.io/1.0/config/configuration-file.html module.exports = function (config) { - config.set({ - basePath: '', - frameworks: ['jasmine', '@angular-devkit/build-angular'], - plugins: [ - require('karma-jasmine'), - require('karma-chrome-launcher'), - require('karma-jasmine-html-reporter'), - require('karma-coverage-istanbul-reporter'), - require('@angular-devkit/build-angular/plugins/karma') - ], - client: { - clearContext: false // leave Jasmine Spec Runner output visible in browser - }, - coverageIstanbulReporter: { - dir: require('path').join(__dirname, '../coverage'), - reports: ['html', 'lcovonly'], - fixWebpackSourcePaths: true - }, - reporters: ['progress', 'kjhtml'], - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['Chrome'], - singleRun: false - }); -}; \ No newline at end of file + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require('path').join(__dirname, '../coverage'), + reports: ['html', 'lcovonly'], + fixWebpackSourcePaths: true + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false + }); +}; diff --git a/WEB/src/main.ts b/WEB/src/main.ts index c7b673c..38c4486 100644 --- a/WEB/src/main.ts +++ b/WEB/src/main.ts @@ -1,12 +1,12 @@ -import { enableProdMode } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import {enableProdMode} from '@angular/core'; +import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; -import { AppModule } from './app/app.module'; -import { environment } from './environments/environment'; +import {AppModule} from './app/app.module'; +import {environment} from './environments/environment'; if (environment.production) { - enableProdMode(); + enableProdMode(); } platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); + .catch(err => console.error(err)); diff --git a/WEB/src/polyfills.ts b/WEB/src/polyfills.ts index ee8b84d..3492469 100644 --- a/WEB/src/polyfills.ts +++ b/WEB/src/polyfills.ts @@ -59,20 +59,20 @@ * user can disable parts of macroTask/DomEvents patch by setting following flags */ - // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame - // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick - // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames +// (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame +// (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick +// (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames - /* - * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js - * with the following flag, it will bypass `zone.js` patch for IE/Edge - */ +/* +* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js +* with the following flag, it will bypass `zone.js` patch for IE/Edge +*/ // (window as any).__Zone_enable_cross_context_check = true; /*************************************************************************************************** * Zone JS is required by default for Angular itself. */ -import 'zone.js/dist/zone'; // Included with Angular CLI. +import 'zone.js/dist/zone'; // Included with Angular CLI. /*************************************************************************************************** diff --git a/WEB/src/styles.less b/WEB/src/styles.less index 92e0749..4b3ed22 100644 --- a/WEB/src/styles.less +++ b/WEB/src/styles.less @@ -19,17 +19,21 @@ html { overflow: hidden; border-radius: 8px; transition: all 300ms ease-in-out; + .mat-table tbody { background: none; } + th.mat-header-cell:first-of-type { border-top-left-radius: 8px; transition: all 300ms ease-in-out; } + th.mat-header-cell:last-of-type { border-top-right-radius: 8px; transition: all 300ms ease-in-out; } + .mat-table thead { border-top-right-radius: 8px; border-top-left-radius: 8px; @@ -40,13 +44,16 @@ html { tr.selected { background-color: #0002; } + tr:hover { cursor: pointer; background-color: #0001; + td { color: #ff9900; } } + td.mat-cell { padding: 0 5px; } @@ -58,14 +65,17 @@ html { bottom: 0; right: 70vw; border-radius: 0px; + th.mat-header-cell:first-of-type { border-top-left-radius: 0px; transition: all 300ms ease-in-out; } + th.mat-header-cell:last-of-type { border-top-right-radius: 0px; transition: all 300ms ease-in-out; } + .mat-table thead { border-top-right-radius: 0px; border-top-left-radius: 0px; @@ -95,9 +105,11 @@ html { .song-detail-container { margin-left: 30vw; + .mat-form-field-infix { width: 80px; } + .mat-radio-button { margin: 15px 10px 0 10px; } @@ -106,15 +118,17 @@ html { .mat-card { padding: 0; } + table { width: 100%; background: none; box-shadow: none; } + td.mat-cell:last-of-type, td.mat-footer-cell:last-of-type, th.mat-header-cell:last-of-type { padding-right: 8px; text-align: right; - } + } } } diff --git a/WEB/src/test.ts b/WEB/src/test.ts index 1631789..ea75c8e 100644 --- a/WEB/src/test.ts +++ b/WEB/src/test.ts @@ -1,18 +1,15 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'zone.js/dist/zone-testing'; -import { getTestBed } from '@angular/core/testing'; -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting -} from '@angular/platform-browser-dynamic/testing'; +import {getTestBed} from '@angular/core/testing'; +import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing'; declare const require: any; // First, initialize the Angular testing environment. getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting() + BrowserDynamicTestingModule, + platformBrowserDynamicTesting() ); // Then we find all the tests. const context = require.context('./', true, /\.spec\.ts$/); diff --git a/WEB/src/tslint.json b/WEB/src/tslint.json index 52e2c1a..aa7c3ee 100644 --- a/WEB/src/tslint.json +++ b/WEB/src/tslint.json @@ -1,17 +1,17 @@ { - "extends": "../tslint.json", - "rules": { - "directive-selector": [ - true, - "attribute", - "app", - "camelCase" - ], - "component-selector": [ - true, - "element", - "app", - "kebab-case" - ] - } + "extends": "../tslint.json", + "rules": { + "directive-selector": [ + true, + "attribute", + "app", + "camelCase" + ], + "component-selector": [ + true, + "element", + "app", + "kebab-case" + ] + } }