update tslint -> eslint

This commit is contained in:
2021-05-21 20:17:26 +02:00
parent 80260df71f
commit a195fafa6b
252 changed files with 3080 additions and 2420 deletions

View File

@@ -1,26 +1,29 @@
<app-card heading="Angehängte Dateien">
<div *ngIf="currentUpload">
<div class="progress">
<div [ngStyle]="{ 'width': currentUpload?.progress + '%' }" class="progress-bar progress-bar-animated"></div>
<div
[ngStyle]="{ width: currentUpload?.progress + '%' }"
class="progress-bar progress-bar-animated"
></div>
</div>
Progress: {{currentUpload?.name}} | {{currentUpload?.progress}}% Complete
Progress: {{ currentUpload?.name }} | {{ currentUpload?.progress }}%
Complete
</div>
<div class="upload">
<label>
<input (change)="detectFiles($event)" type="file">
<input (change)="detectFiles($event)" type="file"/>
</label>
<button (click)="uploadSingle()"
[disabled]="!selectedFiles"
mat-icon-button>
<button
(click)="uploadSingle()"
[disabled]="!selectedFiles"
mat-icon-button
>
<mat-icon>cloud_upload</mat-icon>
</button>
</div>
<p *ngFor="let file of (files$|async)">
<p *ngFor="let file of files$ | async">
<app-file [file]="file" [songId]="songId"></app-file>
</p>
</app-card>

View File

@@ -6,12 +6,13 @@ describe('EditFileComponent', () => {
let component: EditFileComponent;
let fixture: ComponentFixture<EditFileComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [EditFileComponent]
beforeEach(
waitForAsync(() => {
void TestBed.configureTestingModule({
declarations: [EditFileComponent],
}).compileComponents();
})
.compileComponents();
}));
);
beforeEach(() => {
fixture = TestBed.createComponent(EditFileComponent);
@@ -20,6 +21,6 @@ describe('EditFileComponent', () => {
});
it('should create', () => {
expect(component).toBeTruthy();
void expect(component).toBeTruthy();
});
});

View File

@@ -10,41 +10,33 @@ import {File} from '../../../services/file';
@Component({
selector: 'app-edit-file',
templateUrl: './edit-file.component.html',
styleUrls: ['./edit-file.component.less']
styleUrls: ['./edit-file.component.less'],
})
export class EditFileComponent {
public selectedFiles: FileList;
public currentUpload: Upload;
public songId: string;
public files$: Observable<File[]>;
constructor(
private activatedRoute: ActivatedRoute,
private uploadService: UploadService,
private fileService: FileDataService,
) {
this.activatedRoute.params.pipe(
map(param => param.songId),
).subscribe(songId => {
public constructor(private activatedRoute: ActivatedRoute, private uploadService: UploadService, private fileService: FileDataService) {
this.activatedRoute.params.pipe(map((param: {songId: string}) => param.songId)).subscribe(songId => {
this.songId = songId;
});
this.files$ = this.activatedRoute.params.pipe(
map(param => param.songId),
map((param: {songId: string}) => param.songId),
switchMap(songId => this.fileService.read$(songId))
);
}
detectFiles(event) {
this.selectedFiles = event.target.files;
public detectFiles(event: Event): void {
const target = event.target as HTMLInputElement;
this.selectedFiles = target.files;
}
public async uploadSingle() {
public uploadSingle(): void {
const file = this.selectedFiles.item(0);
this.currentUpload = new Upload(file as any);
await this.uploadService.pushUpload(this.songId, this.currentUpload);
this.currentUpload = new Upload(file);
this.uploadService.pushUpload(this.songId, this.currentUpload);
}
}

View File

@@ -2,4 +2,4 @@
<fa-icon [icon]="faTrash"></fa-icon>
</button>
<a [href]="url$|async" target="_blank">{{name}}</a>
<a [href]="url$ | async" target="_blank">{{ name }}</a>

View File

@@ -6,12 +6,13 @@ describe('FileComponent', () => {
let component: FileComponent;
let fixture: ComponentFixture<FileComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [FileComponent]
beforeEach(
waitForAsync(() => {
void TestBed.configureTestingModule({
declarations: [FileComponent],
}).compileComponents();
})
.compileComponents();
}));
);
beforeEach(() => {
fixture = TestBed.createComponent(FileComponent);
@@ -20,6 +21,6 @@ describe('FileComponent', () => {
});
it('should create', () => {
expect(component).toBeTruthy();
void expect(component).toBeTruthy();
});
});

View File

@@ -7,20 +7,20 @@ import {FileService} from '../../../../services/file.service';
@Component({
selector: 'app-file',
templateUrl: './file.component.html',
styleUrls: ['./file.component.less']
styleUrls: ['./file.component.less'],
})
export class FileComponent {
public url$: Observable<string>;
public name: string;
public faTrash = faTrashAlt;
@Input() songId: string;
@Input() public songId: string;
private fileId: string;
private path: string;
constructor(private fileService: FileService) {
}
public constructor(private fileService: FileService) {}
@Input() set file(file: File) {
@Input()
public set file(file: File) {
this.url$ = this.fileService.getDownloadUrl(file.path + '/' + file.name);
this.name = file.name;
this.fileId = file.id;

View File

@@ -6,11 +6,11 @@ describe('EditSongGuard', () => {
let guard: EditSongGuard;
beforeEach(() => {
TestBed.configureTestingModule({});
void TestBed.configureTestingModule({});
guard = TestBed.inject(EditSongGuard);
});
it('should be created', () => {
expect(guard).toBeTruthy();
void expect(guard).toBeTruthy();
});
});

View File

@@ -4,16 +4,15 @@ import {Observable} from 'rxjs';
import {EditComponent} from './edit.component';
@Injectable({
providedIn: 'root'
providedIn: 'root',
})
export class EditSongGuard implements CanDeactivate<unknown> {
canDeactivate(
public canDeactivate(
component: EditComponent,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState?: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
nextState?: RouterStateSnapshot
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return component.editSongComponent.askForSave(nextState);
}
}

View File

@@ -1,48 +1,58 @@
<app-card *ngIf="song" [heading]="song.number + ' bearbeiten'" closeLink="../">
<form [formGroup]="form" class="form">
<mat-form-field appearance="outline">
<mat-label>Titel</mat-label>
<input formControlName="title" matInput>
<input formControlName="title" matInput/>
</mat-form-field>
<div class="fourth">
<mat-form-field appearance="outline">
<mat-label>Typ</mat-label>
<mat-select formControlName="type">
<mat-option *ngFor="let type of types" [value]="type">{{type | songType}}</mat-option>
<mat-option *ngFor="let type of types" [value]="type">{{
type | songType
}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Tonart</mat-label>
<mat-select formControlName="key">
<mat-option *ngFor="let key of keys" [value]="key">{{key|key}}</mat-option>
<mat-option *ngFor="let key of keys" [value]="key">{{
key | key
}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Tempo</mat-label>
<input formControlName="tempo" matInput>
<input formControlName="tempo" matInput/>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Status</mat-label>
<mat-select formControlName="status">
<mat-option *ngFor="let status of status" [value]="status">{{status | status}}</mat-option>
<mat-option *ngFor="let status of status" [value]="status">{{
status | status
}}</mat-option>
</mat-select>
</mat-form-field>
</div>
<mat-form-field appearance="outline">
<mat-label>Songtext</mat-label>
<textarea (focus)="songtextFocus=true" (focusout)="songtextFocus=false" [mat-autosize]="true"
formControlName="text" matInput></textarea>
<textarea
(focus)="songtextFocus = true"
(focusout)="songtextFocus = false"
[mat-autosize]="true"
formControlName="text"
matInput
></textarea>
</mat-form-field>
<div *ngIf="songtextFocus" class="song-text-help">
<h3>Vorschau</h3>
<app-song-text [text]="form.value.text" chordMode="show"></app-song-text>
<h3>Hinweise zur Bearbeitung</h3>
<h4>Aufbau</h4>
Der Liedtext wird hintereinander weg geschrieben. Dabei werden Strophen, Refrain und Bridge jeweils durch
eine zusätzliche Zeile Markiert. z.B.
Der Liedtext wird hintereinander weg geschrieben. Dabei werden Strophen,
Refrain und Bridge jeweils durch eine zusätzliche Zeile Markiert. z.B.
<pre>
Strophe
Text der ersten Strophe
@@ -54,9 +64,10 @@
Und hier der Refrain
</pre>
<h3>Akkorde</h3>
Die Akktorde werden jeweils in der Zeile über dem jeweiligen Liedtext geschrieben.
Sie werden jeweils durch Leerzeichen an die entsprechende Position gebracht.
Bitte keine Tabulatoren verwenden! Folgende Schreibweisen sind erlaubt:
Die Akktorde werden jeweils in der Zeile über dem jeweiligen Liedtext
geschrieben. Sie werden jeweils durch Leerzeichen an die entsprechende
Position gebracht. Bitte keine Tabulatoren verwenden! Folgende
Schreibweisen sind erlaubt:
<pre>
Dur: C D E
Moll: c d e
@@ -76,21 +87,31 @@
<mat-form-field appearance="outline">
<mat-label>Kommentar</mat-label>
<textarea [mat-autosize]="true" formControlName="comment" matInput></textarea>
<textarea
[mat-autosize]="true"
formControlName="comment"
matInput
></textarea>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-chip-list #chipList>
<mat-chip (removed)="removeFlag(flag)" *ngFor="let flag of flags"
[removable]="true" [selectable]="false">
{{flag}}&nbsp;
<mat-chip
(removed)="removeFlag(flag)"
*ngFor="let flag of flags"
[removable]="true"
[selectable]="false"
>
{{ flag }}&nbsp;
<fa-icon (click)="removeFlag(flag)" [icon]="faRemove"></fa-icon>
</mat-chip>
<input (matChipInputTokenEnd)="addFlag($event)"
[matChipInputAddOnBlur]="true"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
placeholder="Attribute">
<input
(matChipInputTokenEnd)="addFlag($event)"
[matChipInputAddOnBlur]="true"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
placeholder="Attribute"
/>
</mat-chip-list>
</mat-form-field>
@@ -98,54 +119,62 @@
<mat-form-field appearance="outline">
<mat-label>Rechtlicher Status</mat-label>
<mat-select formControlName="legalType">
<mat-option *ngFor="let key of legalType" [value]="key">{{key|legalType}}</mat-option>
<mat-option *ngFor="let key of legalType" [value]="key">{{
key | legalType
}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Rechteinhaber</mat-label>
<mat-select formControlName="legalOwner">
<mat-option *ngFor="let key of legalOwner" [value]="key">{{key|legalOwner}}</mat-option>
<mat-option *ngFor="let key of legalOwner" [value]="key">{{
key | legalOwner
}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Rechteinhaber ID (z.B. CCLI Liednummer)</mat-label>
<input formControlName="legalOwnerId" matInput>
<a *ngIf="form.value.legalOwner==='CCLI'" class="link-ccli"
href="https://songselect.ccli.com/Songs/{{form.value.legalOwnerId}}"
matSuffix
matTooltip="CCLI Link: https://songselect.ccli.com/Songs/{{form.value.legalOwnerId}}"
matTooltipPosition="before" target="_blank">
<input formControlName="legalOwnerId" matInput/>
<a
*ngIf="form.value.legalOwner === 'CCLI'"
class="link-ccli"
href="https://songselect.ccli.com/Songs/{{ form.value.legalOwnerId }}"
matSuffix
matTooltip="CCLI Link: https://songselect.ccli.com/Songs/{{
form.value.legalOwnerId
}}"
matTooltipPosition="before"
target="_blank"
>
<fa-icon [icon]="faLink"></fa-icon>
</a>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Künstler</mat-label>
<input formControlName="artist" matInput>
<input formControlName="artist" matInput/>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Verlag</mat-label>
<input formControlName="label" matInput>
<input formControlName="label" matInput/>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Nutzungsbedingungen</mat-label>
<input formControlName="termsOfUse" matInput>
<input formControlName="termsOfUse" matInput/>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>abweichende Quelle</mat-label>
<input formControlName="origin" matInput>
<input formControlName="origin" matInput/>
</mat-form-field>
</div>
</form>
<app-button-row>
<app-button (click)="onSave()" [icon]="faSave">Speichern</app-button>
</app-button-row>
</app-card>

View File

@@ -6,12 +6,13 @@ describe('EditSongComponent', () => {
let component: EditSongComponent;
let fixture: ComponentFixture<EditSongComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [EditSongComponent]
beforeEach(
waitForAsync(() => {
void TestBed.configureTestingModule({
declarations: [EditSongComponent],
}).compileComponents();
})
.compileComponents();
}));
);
beforeEach(() => {
fixture = TestBed.createComponent(EditSongComponent);
@@ -20,6 +21,6 @@ describe('EditSongComponent', () => {
});
it('should create', () => {
expect(component).toBeTruthy();
void expect(component).toBeTruthy();
});
});

View File

@@ -17,7 +17,7 @@ import {SaveDialogComponent} from './save-dialog/save-dialog.component';
@Component({
selector: 'app-edit-song',
templateUrl: './edit-song.component.html',
styleUrls: ['./edit-song.component.less']
styleUrls: ['./edit-song.component.less'],
})
export class EditSongComponent implements OnInit {
public song: Song;
@@ -28,36 +28,31 @@ export class EditSongComponent implements OnInit {
public legalOwner = SongService.LEGAL_OWNER;
public legalType = SongService.LEGAL_TYPE;
public flags: string[] = [];
readonly separatorKeysCodes: number[] = [ENTER, COMMA];
public readonly separatorKeysCodes: number[] = [ENTER, COMMA];
public faRemove = faTimesCircle;
public faSave = faSave;
public faLink = faExternalLinkAlt;
public songtextFocus = false;
constructor(
private activatedRoute: ActivatedRoute,
private songService: SongService,
private editService: EditService,
private router: Router,
public dialog: MatDialog
) {
}
public constructor(private activatedRoute: ActivatedRoute, private songService: SongService, private editService: EditService, private router: Router, public dialog: MatDialog) {}
public ngOnInit(): void {
this.activatedRoute.params.pipe(
map(param => param.songId),
switchMap(songId => this.songService.read$(songId)),
first()
).subscribe(song => {
this.song = song;
this.form = this.editService.createSongForm(song);
this.form.controls.flags.valueChanges.subscribe(_ => this.onFlagsChanged(_));
this.onFlagsChanged(this.form.controls.flags.value);
});
this.activatedRoute.params
.pipe(
map((param: {songId: string}) => param.songId),
switchMap(songId => this.songService.read$(songId)),
first()
)
.subscribe(song => {
this.song = song;
this.form = this.editService.createSongForm(song);
this.form.controls.flags.valueChanges.subscribe(_ => this.onFlagsChanged(_));
this.onFlagsChanged(this.form.controls.flags.value);
});
}
public async onSave(): Promise<void> {
const data = this.form.value;
const data = this.form.value as Partial<Song>;
await this.songService.update$(this.song.id, data);
this.form.markAsPristine();
await this.router.navigateByUrl('songs/' + this.song.id);
@@ -83,6 +78,22 @@ export class EditSongComponent implements OnInit {
}
}
public askForSave(nextState?: RouterStateSnapshot): boolean {
if (!this.form.dirty) {
return true;
}
const dialogRef = this.dialog.open(SaveDialogComponent, {
width: '350px',
});
dialogRef.afterClosed().subscribe((save: boolean) => {
void this.onSaveDialogAfterClosed(save, nextState.url).then();
});
return false;
}
private onFlagsChanged(flagArray: string): void {
if (!flagArray) {
this.flags = [];
@@ -92,30 +103,13 @@ export class EditSongComponent implements OnInit {
this.flags = flagArray.split(';').filter(_ => !!_);
}
public askForSave(nextState?: RouterStateSnapshot): boolean {
if (!this.form.dirty) {
return true;
}
const dialogRef = this.dialog.open(SaveDialogComponent, {
width: '350px'
});
dialogRef.afterClosed().subscribe((save: boolean) => {
this.onSaveDialogAfterClosed(save, nextState.url).then();
});
return false;
}
private async onSaveDialogAfterClosed(save: boolean, url: string) {
if (save) {
const data = this.form.value;
const data = this.form.value as Partial<Song>;
await this.songService.update$(this.song.id, data);
}
this.form.markAsPristine();
await this.router.navigateByUrl(url);
}
}

View File

@@ -4,5 +4,7 @@
</div>
<div mat-dialog-actions>
<button [mat-dialog-close]="false" mat-button>Änderungen verwerfen</button>
<button [mat-dialog-close]="true" cdkFocusInitial mat-button>Speichern</button>
<button [mat-dialog-close]="true" cdkFocusInitial mat-button>
Speichern
</button>
</div>

View File

@@ -6,12 +6,13 @@ describe('SaveDialogComponent', () => {
let component: SaveDialogComponent;
let fixture: ComponentFixture<SaveDialogComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [SaveDialogComponent]
beforeEach(
waitForAsync(() => {
void TestBed.configureTestingModule({
declarations: [SaveDialogComponent],
}).compileComponents();
})
.compileComponents();
}));
);
beforeEach(() => {
fixture = TestBed.createComponent(SaveDialogComponent);
@@ -20,6 +21,6 @@ describe('SaveDialogComponent', () => {
});
it('should create', () => {
expect(component).toBeTruthy();
void expect(component).toBeTruthy();
});
});

View File

@@ -1,16 +1,8 @@
import {Component, OnInit} from '@angular/core';
import {Component} from '@angular/core';
@Component({
selector: 'app-save-dialog',
templateUrl: './save-dialog.component.html',
styleUrls: ['./save-dialog.component.less']
styleUrls: ['./save-dialog.component.less'],
})
export class SaveDialogComponent implements OnInit {
constructor() {
}
ngOnInit(): void {
}
}
export class SaveDialogComponent {}

View File

@@ -6,12 +6,13 @@ describe('EditComponent', () => {
let component: EditComponent;
let fixture: ComponentFixture<EditComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [EditComponent]
beforeEach(
waitForAsync(() => {
void TestBed.configureTestingModule({
declarations: [EditComponent],
}).compileComponents();
})
.compileComponents();
}));
);
beforeEach(() => {
fixture = TestBed.createComponent(EditComponent);
@@ -20,6 +21,6 @@ describe('EditComponent', () => {
});
it('should create', () => {
expect(component).toBeTruthy();
void expect(component).toBeTruthy();
});
});

View File

@@ -4,7 +4,7 @@ import {EditSongComponent} from './edit-song/edit-song.component';
@Component({
selector: 'app-edit',
templateUrl: './edit.component.html',
styleUrls: ['./edit.component.less']
styleUrls: ['./edit.component.less'],
})
export class EditComponent {
@ViewChild(EditSongComponent) public editSongComponent: EditSongComponent;

View File

@@ -27,7 +27,6 @@ import {MatDialogModule} from '@angular/material/dialog';
import {HistoryComponent} from './history/history.component';
import {SongTextModule} from '../../../../widget-modules/components/song-text/song-text.module';
@NgModule({
declarations: [EditComponent, EditSongComponent, EditFileComponent, FileComponent, SaveDialogComponent, HistoryComponent],
exports: [EditComponent],
@@ -56,8 +55,6 @@ import {SongTextModule} from '../../../../widget-modules/components/song-text/so
MatTooltipModule,
MatDialogModule,
SongTextModule,
]
],
})
export class EditModule {
}
export class EditModule {}

View File

@@ -3,10 +3,10 @@ import {TestBed} from '@angular/core/testing';
import {EditService} from './edit.service';
describe('EditService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
beforeEach(() => void TestBed.configureTestingModule({}));
it('should be created', () => {
const service: EditService = TestBed.get(EditService);
expect(service).toBeTruthy();
const service: EditService = TestBed.inject(EditService);
void expect(service).toBeTruthy();
});
});

View File

@@ -3,13 +3,9 @@ import {Song} from '../../services/song';
import {FormControl, FormGroup} from '@angular/forms';
@Injectable({
providedIn: 'root'
providedIn: 'root',
})
export class EditService {
constructor() {
}
public createSongForm(song: Song): FormGroup {
return new FormGroup({
text: new FormControl(song.text),

View File

@@ -1,6 +1,6 @@
<app-card *ngIf="song && song.edits" heading="letzte Änderungen">
<div *ngFor="let edit of song.edits" class="list">
<div>{{edit.username}}</div>
<div>{{edit.timestamp.toDate()|date:'dd.MM.yyyy'}}</div>
<div>{{ edit.username }}</div>
<div>{{ edit.timestamp.toDate() | date: "dd.MM.yyyy" }}</div>
</div>
</app-card>

View File

@@ -6,12 +6,13 @@ describe('HistoryComponent', () => {
let component: HistoryComponent;
let fixture: ComponentFixture<HistoryComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [HistoryComponent]
beforeEach(
waitForAsync(() => {
void TestBed.configureTestingModule({
declarations: [HistoryComponent],
}).compileComponents();
})
.compileComponents();
}));
);
beforeEach(() => {
fixture = TestBed.createComponent(HistoryComponent);
@@ -20,6 +21,6 @@ describe('HistoryComponent', () => {
});
it('should create', () => {
expect(component).toBeTruthy();
void expect(component).toBeTruthy();
});
});

View File

@@ -7,25 +7,22 @@ import {Song} from '../../../services/song';
@Component({
selector: 'app-history',
templateUrl: './history.component.html',
styleUrls: ['./history.component.less']
styleUrls: ['./history.component.less'],
})
export class HistoryComponent implements OnInit {
public song: Song;
constructor(
private activatedRoute: ActivatedRoute,
private songService: SongService,
) {
}
public constructor(private activatedRoute: ActivatedRoute, private songService: SongService) {}
public ngOnInit(): void {
this.activatedRoute.params.pipe(
map(param => param.songId),
switchMap(songId => this.songService.read$(songId)),
first()
).subscribe(song => {
this.song = song;
});
this.activatedRoute.params
.pipe(
map((param: {songId: string}) => param.songId),
switchMap(songId => this.songService.read$(songId)),
first()
)
.subscribe(song => {
this.song = song;
});
}
}