diff --git a/package-lock.json b/package-lock.json index 2faf647..1d3a364 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11122,6 +11122,11 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, + "ngx-hocs-unsubscriber": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/ngx-hocs-unsubscriber/-/ngx-hocs-unsubscriber-1.1.7.tgz", + "integrity": "sha512-FPasZvptGjzcnWzlUJcVhqq+mFi0bGt4/txTHe0XX6kDlIRX+9yfnPPDXvUvSSj6yXeuWDfnh9kn5Fr74W9Ohw==" + }, "ngx-mat-select-search": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ngx-mat-select-search/-/ngx-mat-select-search-2.1.2.tgz", diff --git a/package.json b/package.json index 76871e7..66d05b0 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "@fortawesome/free-solid-svg-icons": "^5.13.0", "docx": "^5.0.2", "firebase": ">= 5.5.7 <8", + "ngx-hocs-unsubscriber": "^1.1.7", "ngx-mat-select-search": "^2.1.2", "ngx-perfect-scrollbar": "^9.0.0", "rxjs": "~6.5.5", diff --git a/src/app/modules/songs/services/song-data.service.ts b/src/app/modules/songs/services/song-data.service.ts index ad8f8f7..41a94a1 100644 --- a/src/app/modules/songs/services/song-data.service.ts +++ b/src/app/modules/songs/services/song-data.service.ts @@ -7,11 +7,14 @@ import {DbService} from '../../../services/db.service'; providedIn: 'root' }) export class SongDataService { + private collection = 'songs'; + constructor(private dbService: DbService) { } - public list$ = (): Observable => this.dbService.col$('songs'); - public read$ = (songId: string): Observable => this.dbService.doc$('songs/' + songId); - public update$ = async (songId: string, data: any): Promise => await this.dbService.doc('songs/' + songId).update(data); + public list$ = (): Observable => this.dbService.col$(this.collection); + public read$ = (songId: string): Observable => this.dbService.doc$(this.collection + '/' + songId); + public update$ = async (songId: string, data: Partial): Promise => await this.dbService.doc(this.collection + '/' + songId).update(data); + public add = async (data: Partial): Promise => (await this.dbService.col(this.collection).add(data)).id } diff --git a/src/app/modules/songs/services/song.service.ts b/src/app/modules/songs/services/song.service.ts index 558e775..2af9d01 100644 --- a/src/app/modules/songs/services/song.service.ts +++ b/src/app/modules/songs/services/song.service.ts @@ -32,6 +32,10 @@ export class SongService { await this.songDataService.update$(songId, data); } + public async new(number: number, title: string): Promise { + return await this.songDataService.add({number, title, status: 'draft', legalType: 'open'}) + } + // https://www.csvjson.com/csv2json private async updateFromCLI(songs: Song[]) { const mapped = songs.map(_ => ({ diff --git a/src/app/modules/songs/song/new/new.component.html b/src/app/modules/songs/song/new/new.component.html new file mode 100644 index 0000000..64a4542 --- /dev/null +++ b/src/app/modules/songs/song/new/new.component.html @@ -0,0 +1,18 @@ + + +
+ + Nummer + + + + Titel + + +
+ + + Anlegen + +
+ diff --git a/src/app/modules/songs/song/new/new.component.less b/src/app/modules/songs/song/new/new.component.less new file mode 100644 index 0000000..d052e94 --- /dev/null +++ b/src/app/modules/songs/song/new/new.component.less @@ -0,0 +1,5 @@ +.split { + display: grid; + grid-template-columns: 70px auto; + column-gap: 20px; +} diff --git a/src/app/modules/songs/song/new/new.component.spec.ts b/src/app/modules/songs/song/new/new.component.spec.ts new file mode 100644 index 0000000..9b23afc --- /dev/null +++ b/src/app/modules/songs/song/new/new.component.spec.ts @@ -0,0 +1,25 @@ +import {async, ComponentFixture, TestBed} from '@angular/core/testing'; + +import {NewComponent} from './new.component'; + +describe('NewComponent', () => { + let component: NewComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [NewComponent] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(NewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/modules/songs/song/new/new.component.ts b/src/app/modules/songs/song/new/new.component.ts new file mode 100644 index 0000000..9dbed3c --- /dev/null +++ b/src/app/modules/songs/song/new/new.component.ts @@ -0,0 +1,47 @@ +import {Component, OnInit} from '@angular/core'; +import {faSave} from '@fortawesome/free-solid-svg-icons/faSave'; +import {FormControl, FormGroup, Validators} from '@angular/forms'; +import {autoComplete, Unsubscriber} from 'ngx-hocs-unsubscriber'; +import {SongService} from '../../services/song.service'; +import {Song} from '../../services/song'; +import {Router} from '@angular/router'; + +@Unsubscriber() +@Component({ + selector: 'app-new', + templateUrl: './new.component.html', + styleUrls: ['./new.component.less'] +}) +export class NewComponent implements OnInit { + public faSave = faSave; + public form: FormGroup; + + constructor(private songService: SongService, private router: Router) { + } + + public ngOnInit(): void { + this.form = new FormGroup({ + number: new FormControl(null, Validators.required), + title: new FormControl(null, Validators.required), + }) + + this.songService.list$().pipe(autoComplete(this)).subscribe(songs => { + const freeSongnumber = this.getFreeSongNumber(songs); + this.form.controls.number.setValue(freeSongnumber); + }) + } + + public async onSave(): Promise { + const number = this.form.value.number; + const title = this.form.value.title; + const newSongId = await this.songService.new(number, title); + await this.router.navigateByUrl('/songs/' + newSongId + '/edit'); + } + + private getFreeSongNumber(songs: Song[]): Number { + const numbers = songs.map(_ => _.number); + for (let i = 1; i < Number.MAX_SAFE_INTEGER; i++) { + if (!numbers.some(_ => _ === i)) return i; + } + } +} diff --git a/src/app/modules/songs/song/new/new.module.ts b/src/app/modules/songs/song/new/new.module.ts new file mode 100644 index 0000000..a553066 --- /dev/null +++ b/src/app/modules/songs/song/new/new.module.ts @@ -0,0 +1,27 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {NewComponent} from './new.component'; +import {CardModule} from '../../../../widget-modules/components/card/card.module'; +import {ReactiveFormsModule} from '@angular/forms'; +import {MatFormFieldModule} from '@angular/material/form-field'; +import {MatInputModule} from '@angular/material/input'; +import {ButtonRowModule} from '../../../../widget-modules/components/button-row/button-row.module'; +import {ButtonModule} from '../../../../widget-modules/components/button/button.module'; +import {AutofocusModule} from '../../../../widget-modules/directives/autofocus/autofocus.module'; + + +@NgModule({ + declarations: [NewComponent], + imports: [ + CommonModule, + CardModule, + ReactiveFormsModule, + MatFormFieldModule, + MatInputModule, + ButtonRowModule, + ButtonModule, + AutofocusModule + ] +}) +export class NewModule { +} diff --git a/src/app/modules/songs/songs-routing.module.ts b/src/app/modules/songs/songs-routing.module.ts index 82f6ec7..c1b4d53 100644 --- a/src/app/modules/songs/songs-routing.module.ts +++ b/src/app/modules/songs/songs-routing.module.ts @@ -3,6 +3,7 @@ import {RouterModule, Routes} from '@angular/router'; import {SongComponent} from './song/song.component'; import {SongListComponent} from './song-list/song-list.component'; import {EditComponent} from './song/edit/edit.component'; +import {NewComponent} from './song/new/new.component'; const routes: Routes = [ @@ -11,6 +12,10 @@ const routes: Routes = [ component: SongListComponent, pathMatch: 'full' }, + { + path: 'new', + component: NewComponent + }, { path: ':songId/edit', component: EditComponent diff --git a/src/app/modules/songs/songs.module.ts b/src/app/modules/songs/songs.module.ts index 6a9eee1..bbcb972 100644 --- a/src/app/modules/songs/songs.module.ts +++ b/src/app/modules/songs/songs.module.ts @@ -5,6 +5,7 @@ import {SongsRoutingModule} from './songs-routing.module'; import {SongListModule} from './song-list/song-list.module'; import {SongModule} from './song/song.module'; import {EditModule} from './song/edit/edit.module'; +import {NewModule} from './song/new/new.module'; @NgModule({ declarations: [], @@ -13,7 +14,8 @@ import {EditModule} from './song/edit/edit.module'; SongsRoutingModule, SongListModule, SongModule, - EditModule + EditModule, + NewModule, ] }) export class SongsModule { diff --git a/src/app/widget-modules/directives/autofocus/autofocus.directive.ts b/src/app/widget-modules/directives/autofocus/autofocus.directive.ts new file mode 100644 index 0000000..77c8b24 --- /dev/null +++ b/src/app/widget-modules/directives/autofocus/autofocus.directive.ts @@ -0,0 +1,23 @@ +import {Directive, ElementRef, Input} from "@angular/core"; + +@Directive({ + selector: "[autofocus]" +}) +export class AutofocusDirective { + private focus = true; + + constructor(private el: ElementRef) { + } + + @Input() set autofocus(condition: boolean) { + this.focus = condition !== false; + } + + public ngOnInit(): void { + if (this.focus) { + window.setTimeout(() => { + this.el.nativeElement.focus(); + }); + } + } +} diff --git a/src/app/widget-modules/directives/autofocus/autofocus.module.ts b/src/app/widget-modules/directives/autofocus/autofocus.module.ts new file mode 100644 index 0000000..bac861f --- /dev/null +++ b/src/app/widget-modules/directives/autofocus/autofocus.module.ts @@ -0,0 +1,16 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {AutofocusDirective} from './autofocus.directive'; + + +@NgModule({ + declarations: [AutofocusDirective], + exports: [ + AutofocusDirective + ], + imports: [ + CommonModule + ] +}) +export class AutofocusModule { +}