file upload
This commit is contained in:
@@ -7,6 +7,10 @@ service cloud.firestore {
|
|||||||
match /songs/{song} {
|
match /songs/{song} {
|
||||||
allow read: if true;
|
allow read: if true;
|
||||||
allow write: if true;
|
allow write: if true;
|
||||||
|
}
|
||||||
|
match /songs/{song}/files/{file} {
|
||||||
|
allow read: if true;
|
||||||
|
allow write: if true;
|
||||||
}
|
}
|
||||||
match /lastmodified/{lastmodified} {
|
match /lastmodified/{lastmodified} {
|
||||||
allow read: if true;
|
allow read: if true;
|
||||||
|
|||||||
1936
package-lock.json
generated
1936
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -34,8 +34,8 @@
|
|||||||
"zone.js": "~0.9.1"
|
"zone.js": "~0.9.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "~0.803.19",
|
"@angular-devkit/build-angular": "~0.803.20",
|
||||||
"@angular/cli": "~8.3.19",
|
"@angular/cli": "~8.3.20",
|
||||||
"@angular/compiler-cli": "~8.2.14",
|
"@angular/compiler-cli": "~8.2.14",
|
||||||
"@angular/language-service": "~8.2.14",
|
"@angular/language-service": "~8.2.14",
|
||||||
"@types/node": "~8.9.4",
|
"@types/node": "~8.9.4",
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
|||||||
import {ApplicationFrameModule} from './application-frame/application-frame.module';
|
import {ApplicationFrameModule} from './application-frame/application-frame.module';
|
||||||
import {AngularFireModule} from '@angular/fire';
|
import {AngularFireModule} from '@angular/fire';
|
||||||
import {AngularFirestoreModule} from '@angular/fire/firestore';
|
import {AngularFirestoreModule} from '@angular/fire/firestore';
|
||||||
|
import {AngularFireStorageModule} from '@angular/fire/storage';
|
||||||
|
import {AngularFireDatabaseModule} from '@angular/fire/database';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -26,6 +28,8 @@ import {AngularFirestoreModule} from '@angular/fire/firestore';
|
|||||||
|
|
||||||
AngularFireModule.initializeApp(environment.firebase),
|
AngularFireModule.initializeApp(environment.firebase),
|
||||||
AngularFirestoreModule.enablePersistence(),
|
AngularFirestoreModule.enablePersistence(),
|
||||||
|
AngularFireStorageModule,
|
||||||
|
AngularFireDatabaseModule
|
||||||
|
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [],
|
||||||
|
|||||||
12
src/app/songs/services/file-data.service.spec.ts
Normal file
12
src/app/songs/services/file-data.service.spec.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FileDataService } from './file-data.service';
|
||||||
|
|
||||||
|
describe('FileDataService', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: FileDataService = TestBed.get(FileDataService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
19
src/app/songs/services/file-data.service.ts
Normal file
19
src/app/songs/services/file-data.service.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {SongDataService} from './song-data.service';
|
||||||
|
import {File} from './file';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class FileDataService {
|
||||||
|
|
||||||
|
constructor(private songDataService: SongDataService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public async put(songId: string, file: File): Promise<string> {
|
||||||
|
const songRef = this.songDataService.getSongRef(songId);
|
||||||
|
const fileCollection = songRef.collection('files');
|
||||||
|
const id = await fileCollection.add(file);
|
||||||
|
return id.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/app/songs/services/file.ts
Normal file
5
src/app/songs/services/file.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export interface File {
|
||||||
|
name: string;
|
||||||
|
path: string;
|
||||||
|
createdAt: Date;
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import {AngularFirestore, AngularFirestoreCollection} from '@angular/fire/firest
|
|||||||
import {Song} from '../models/song';
|
import {Song} from '../models/song';
|
||||||
import {Observable} from 'rxjs';
|
import {Observable} from 'rxjs';
|
||||||
import {map} from 'rxjs/operators';
|
import {map} from 'rxjs/operators';
|
||||||
|
import {AngularFirestoreDocument} from '@angular/fire/firestore/document/document';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -23,15 +24,17 @@ export class SongDataService {
|
|||||||
|
|
||||||
public list = (): Observable<Song[]> => this.songs;
|
public list = (): Observable<Song[]> => this.songs;
|
||||||
|
|
||||||
|
public getSongRef = (songId: string): AngularFirestoreDocument<Song> => this.afs.doc<Song>('songs/' + songId);
|
||||||
|
|
||||||
public read(songId: string): Observable<Song | undefined> {
|
public read(songId: string): Observable<Song | undefined> {
|
||||||
return this.afs.doc<Song>('songs/' + songId).valueChanges().pipe(map(song => ({
|
return this.getSongRef(songId).valueChanges().pipe(map(song => ({
|
||||||
...song,
|
...song,
|
||||||
id: songId
|
id: songId
|
||||||
} as Song)));
|
} as Song)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async update(songId: string, data: any): Promise<void> {
|
public async update(songId: string, data: any): Promise<void> {
|
||||||
await this.afs.doc<Song>('songs/' + songId).update(data);
|
await this.getSongRef(songId).update(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,5 +25,4 @@ export class SongService {
|
|||||||
await this.songDataService.update(songId, data);
|
await this.songDataService.update(songId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/app/songs/services/upload.service.spec.ts
Normal file
12
src/app/songs/services/upload.service.spec.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { UploadService } from './upload.service';
|
||||||
|
|
||||||
|
describe('UploadServiceService', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: UploadService = TestBed.get(UploadService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
58
src/app/songs/services/upload.service.ts
Normal file
58
src/app/songs/services/upload.service.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {Upload} from './upload';
|
||||||
|
import {FileDataService} from './file-data.service';
|
||||||
|
import {AngularFireStorage} from '@angular/fire/storage';
|
||||||
|
import {finalize} from 'rxjs/operators';
|
||||||
|
import {File} from './file';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class UploadService {
|
||||||
|
private basePath = '/attachments';
|
||||||
|
|
||||||
|
constructor(private fileDataService: FileDataService, private angularFireStorage: AngularFireStorage) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public async pushUpload(songId: string, upload: Upload) {
|
||||||
|
const path = `${this.basePath}/${songId}`;
|
||||||
|
const filePath = `${path}/${upload.file.name}`;
|
||||||
|
upload.path = path;
|
||||||
|
|
||||||
|
const ref = this.angularFireStorage.ref(filePath);
|
||||||
|
const task = ref.put(upload.file);
|
||||||
|
|
||||||
|
task.percentageChanges().subscribe(percent => upload.progress = percent);
|
||||||
|
task.snapshotChanges().pipe(
|
||||||
|
finalize(() => {
|
||||||
|
this.saveFileData(songId, upload);
|
||||||
|
})
|
||||||
|
).subscribe();
|
||||||
|
|
||||||
|
// const storageRef = storage().ref();
|
||||||
|
// const uploadTask = storageRef.child(`${this.basePath}/${songId}/${file.file.name}`).put(file.file as any);
|
||||||
|
//
|
||||||
|
// uploadTask.on(storage.TaskEvent.STATE_CHANGED,
|
||||||
|
// (snapshot) => {
|
||||||
|
// file.progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
|
||||||
|
// },
|
||||||
|
// (error) => {
|
||||||
|
// console.log(error);
|
||||||
|
// },
|
||||||
|
// () => {
|
||||||
|
// file.url = uploadTask.snapshot.downloadURL;
|
||||||
|
// file.name = file.file.name;
|
||||||
|
// this.saveFileData(songId, file);
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
|
private async saveFileData(songId: string, upload: Upload) {
|
||||||
|
const file: File = {
|
||||||
|
name: upload.file.name,
|
||||||
|
path: upload.path,
|
||||||
|
createdAt: new Date()
|
||||||
|
};
|
||||||
|
await this.fileDataService.put(songId, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/app/songs/services/upload.ts
Normal file
13
src/app/songs/services/upload.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
export class Upload {
|
||||||
|
|
||||||
|
$key: string;
|
||||||
|
file: Upload;
|
||||||
|
name: string;
|
||||||
|
path: string;
|
||||||
|
progress: number;
|
||||||
|
createdAt: Date = new Date();
|
||||||
|
|
||||||
|
constructor(file: Upload) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/app/songs/song/edit/edit-file/edit-file.component.html
Normal file
22
src/app/songs/song/edit/edit-file/edit-file.component.html
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<app-card heading="Angehängte Dateien">
|
||||||
|
|
||||||
|
|
||||||
|
<div *ngIf="currentUpload">
|
||||||
|
<div class="progress">
|
||||||
|
<div class="progress-bar progress-bar-animated" [ngStyle]="{ 'width': currentUpload?.progress + '%' }"></div>
|
||||||
|
</div>
|
||||||
|
Progress: {{currentUpload?.name}} | {{currentUpload?.progress}}% Complete
|
||||||
|
</div>
|
||||||
|
<div class="upload">
|
||||||
|
<label>
|
||||||
|
<input type="file" (change)="detectFiles($event)">
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<button mat-icon-button
|
||||||
|
[disabled]="!selectedFiles"
|
||||||
|
(click)="uploadSingle()">
|
||||||
|
<mat-icon>cloud_upload</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</app-card>
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.upload {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { EditFileComponent } from './edit-file.component';
|
||||||
|
|
||||||
|
describe('EditFileComponent', () => {
|
||||||
|
let component: EditFileComponent;
|
||||||
|
let fixture: ComponentFixture<EditFileComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ EditFileComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(EditFileComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
36
src/app/songs/song/edit/edit-file/edit-file.component.ts
Normal file
36
src/app/songs/song/edit/edit-file/edit-file.component.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {Upload} from '../../../services/upload';
|
||||||
|
import {UploadService} from '../../../services/upload.service';
|
||||||
|
import {ActivatedRoute} from '@angular/router';
|
||||||
|
import {map} from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-edit-file',
|
||||||
|
templateUrl: './edit-file.component.html',
|
||||||
|
styleUrls: ['./edit-file.component.less']
|
||||||
|
})
|
||||||
|
export class EditFileComponent {
|
||||||
|
|
||||||
|
public selectedFiles: FileList;
|
||||||
|
public currentUpload: Upload;
|
||||||
|
public songId: string;
|
||||||
|
|
||||||
|
constructor(private activatedRoute: ActivatedRoute, private uploadService: UploadService) {
|
||||||
|
this.activatedRoute.params.pipe(
|
||||||
|
map(param => param.songId),
|
||||||
|
).subscribe(songId => {
|
||||||
|
this.songId = songId;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
detectFiles(event) {
|
||||||
|
this.selectedFiles = event.target.files;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async uploadSingle() {
|
||||||
|
const file = this.selectedFiles.item(0);
|
||||||
|
this.currentUpload = new Upload(file as any);
|
||||||
|
await this.uploadService.pushUpload(this.songId, this.currentUpload);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
41
src/app/songs/song/edit/edit-song/edit-song.component.html
Normal file
41
src/app/songs/song/edit/edit-song/edit-song.component.html
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<app-card *ngIf="song" [heading]="song.number + ' bearbeiten'">
|
||||||
|
|
||||||
|
<form [formGroup]="form" class="form">
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Titel</mat-label>
|
||||||
|
<input formControlName="title" matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<div class="third">
|
||||||
|
<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-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}}</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Tempo</mat-label>
|
||||||
|
<input formControlName="tempo" matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Songtext</mat-label>
|
||||||
|
<textarea [mat-autosize]="true" formControlName="text" matInput></textarea>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<app-button-row>
|
||||||
|
<button (click)="onSave()" color="primary" mat-flat-button>Speichern</button>
|
||||||
|
<button mat-stroked-button routerLink="../">Abbrechen</button>
|
||||||
|
</app-button-row>
|
||||||
|
</app-card>
|
||||||
|
|
||||||
14
src/app/songs/song/edit/edit-song/edit-song.component.less
Normal file
14
src/app/songs/song/edit/edit-song/edit-song.component.less
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
.form {
|
||||||
|
margin-top: 20px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.third {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
column-gap: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { EditSongComponent } from './edit-song.component';
|
||||||
|
|
||||||
|
describe('EditSongComponent', () => {
|
||||||
|
let component: EditSongComponent;
|
||||||
|
let fixture: ComponentFixture<EditSongComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ EditSongComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(EditSongComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
45
src/app/songs/song/edit/edit-song/edit-song.component.ts
Normal file
45
src/app/songs/song/edit/edit-song/edit-song.component.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import {Song} from '../../../models/song';
|
||||||
|
import {FormGroup} from '@angular/forms';
|
||||||
|
import {ActivatedRoute, Router} from '@angular/router';
|
||||||
|
import {SongService} from '../../../services/song.service';
|
||||||
|
import {EditService} from '../edit.service';
|
||||||
|
import {first, map, switchMap} from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-edit-song',
|
||||||
|
templateUrl: './edit-song.component.html',
|
||||||
|
styleUrls: ['./edit-song.component.less']
|
||||||
|
})
|
||||||
|
export class EditSongComponent implements OnInit {
|
||||||
|
public song: Song;
|
||||||
|
public form: FormGroup;
|
||||||
|
public keys = this.songService.KEYS;
|
||||||
|
public types = this.songService.TYPES;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private activatedRoute: ActivatedRoute,
|
||||||
|
private songService: SongService,
|
||||||
|
private editService: EditService,
|
||||||
|
private router: Router
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onSave(): Promise<void> {
|
||||||
|
const data = this.form.value;
|
||||||
|
await this.songService.update(this.song.id, data);
|
||||||
|
await this.router.navigateByUrl('songs/' + this.song.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,40 +1,2 @@
|
|||||||
<app-card *ngIf="song" [heading]="song.number + ' bearbeiten'">
|
<app-edit-song></app-edit-song>
|
||||||
|
<app-edit-file></app-edit-file>
|
||||||
<form [formGroup]="form" class="form">
|
|
||||||
<mat-form-field appearance="outline">
|
|
||||||
<mat-label>Titel</mat-label>
|
|
||||||
<input formControlName="title" matInput>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<div class="third">
|
|
||||||
<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-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}}</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
<mat-form-field appearance="outline">
|
|
||||||
<mat-label>Tempo</mat-label>
|
|
||||||
<input formControlName="tempo" matInput>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<mat-form-field appearance="outline">
|
|
||||||
<mat-label>Songtext</mat-label>
|
|
||||||
<textarea [mat-autosize]="true" formControlName="text" matInput></textarea>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<app-button-row>
|
|
||||||
<button (click)="onSave()" color="primary" mat-flat-button>Speichern</button>
|
|
||||||
<button mat-stroked-button routerLink="../">Abbrechen</button>
|
|
||||||
</app-button-row>
|
|
||||||
</app-card>
|
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
.form {
|
|
||||||
margin-top: 20px;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.third {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
column-gap: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,44 +1,10 @@
|
|||||||
import {Component, OnInit} from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
import {Song} from '../../models/song';
|
|
||||||
import {ActivatedRoute, Router} from '@angular/router';
|
|
||||||
import {SongService} from '../../services/song.service';
|
|
||||||
import {first, map, switchMap} from 'rxjs/operators';
|
|
||||||
import {FormGroup} from '@angular/forms';
|
|
||||||
import {EditService} from './edit.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-edit',
|
selector: 'app-edit',
|
||||||
templateUrl: './edit.component.html',
|
templateUrl: './edit.component.html',
|
||||||
styleUrls: ['./edit.component.less']
|
styleUrls: ['./edit.component.less']
|
||||||
})
|
})
|
||||||
export class EditComponent implements OnInit {
|
export class EditComponent {
|
||||||
public song: Song;
|
|
||||||
public form: FormGroup;
|
|
||||||
public keys = this.songService.KEYS;
|
|
||||||
public types = this.songService.TYPES;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private activatedRoute: ActivatedRoute,
|
|
||||||
private songService: SongService,
|
|
||||||
private editService: EditService,
|
|
||||||
private router: Router
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async onSave(): Promise<void> {
|
|
||||||
const data = this.form.value;
|
|
||||||
await this.songService.update(this.song.id, data);
|
|
||||||
await this.router.navigateByUrl('songs/' + this.song.id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,13 @@ import {MatSelectModule} from '@angular/material/select';
|
|||||||
import {MatButtonModule} from '@angular/material/button';
|
import {MatButtonModule} from '@angular/material/button';
|
||||||
import {ButtonRowModule} from '../../../widget-modules/components/button-row/button-row.module';
|
import {ButtonRowModule} from '../../../widget-modules/components/button-row/button-row.module';
|
||||||
import {RouterModule} from '@angular/router';
|
import {RouterModule} from '@angular/router';
|
||||||
|
import { EditSongComponent } from './edit-song/edit-song.component';
|
||||||
|
import { EditFileComponent } from './edit-file/edit-file.component';
|
||||||
|
import {MatIconModule} from '@angular/material/icon';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [EditComponent],
|
declarations: [EditComponent, EditSongComponent, EditFileComponent],
|
||||||
exports: [EditComponent],
|
exports: [EditComponent],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@@ -28,6 +31,8 @@ import {RouterModule} from '@angular/router';
|
|||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
ButtonRowModule,
|
ButtonRowModule,
|
||||||
|
|
||||||
|
MatIconModule,
|
||||||
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class EditModule {
|
export class EditModule {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #fffe;
|
background: #fffe;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
width: 800px;
|
||||||
|
|
||||||
&.padding {
|
&.padding {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
|||||||
Reference in New Issue
Block a user