create new title
This commit is contained in:
5
package-lock.json
generated
5
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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<Song[]> => this.dbService.col$('songs');
|
||||
public read$ = (songId: string): Observable<Song | undefined> => this.dbService.doc$('songs/' + songId);
|
||||
public update$ = async (songId: string, data: any): Promise<void> => await this.dbService.doc('songs/' + songId).update(data);
|
||||
public list$ = (): Observable<Song[]> => this.dbService.col$(this.collection);
|
||||
public read$ = (songId: string): Observable<Song | undefined> => this.dbService.doc$(this.collection + '/' + songId);
|
||||
public update$ = async (songId: string, data: Partial<Song>): Promise<void> => await this.dbService.doc(this.collection + '/' + songId).update(data);
|
||||
public add = async (data: Partial<Song>): Promise<string> => (await this.dbService.col(this.collection).add(data)).id
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,10 @@ export class SongService {
|
||||
await this.songDataService.update$(songId, data);
|
||||
}
|
||||
|
||||
public async new(number: number, title: string): Promise<string> {
|
||||
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(_ => ({
|
||||
|
||||
18
src/app/modules/songs/song/new/new.component.html
Normal file
18
src/app/modules/songs/song/new/new.component.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<app-card closeLink="../" heading="Neues Lied">
|
||||
|
||||
<div [formGroup]="form" class="split">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Nummer</mat-label>
|
||||
<input formControlName="number" matInput>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Titel</mat-label>
|
||||
<input autofocus formControlName="title" matInput>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<app-button-row>
|
||||
<app-button (click)="onSave()" [icon]="faSave">Anlegen</app-button>
|
||||
</app-button-row>
|
||||
</app-card>
|
||||
|
||||
5
src/app/modules/songs/song/new/new.component.less
Normal file
5
src/app/modules/songs/song/new/new.component.less
Normal file
@@ -0,0 +1,5 @@
|
||||
.split {
|
||||
display: grid;
|
||||
grid-template-columns: 70px auto;
|
||||
column-gap: 20px;
|
||||
}
|
||||
25
src/app/modules/songs/song/new/new.component.spec.ts
Normal file
25
src/app/modules/songs/song/new/new.component.spec.ts
Normal file
@@ -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<NewComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [NewComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NewComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
47
src/app/modules/songs/song/new/new.component.ts
Normal file
47
src/app/modules/songs/song/new/new.component.ts
Normal file
@@ -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<void> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
27
src/app/modules/songs/song/new/new.module.ts
Normal file
27
src/app/modules/songs/song/new/new.module.ts
Normal file
@@ -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 {
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
Reference in New Issue
Block a user