login
This commit is contained in:
12
src/app/modules/songs/services/file-data.service.spec.ts
Normal file
12
src/app/modules/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();
|
||||
});
|
||||
});
|
||||
34
src/app/modules/songs/services/file-data.service.ts
Normal file
34
src/app/modules/songs/services/file-data.service.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {SongDataService} from './song-data.service';
|
||||
import {File} from './file';
|
||||
import {Observable} from 'rxjs';
|
||||
import {map} from 'rxjs/operators';
|
||||
import {FileServer} from './fileServer';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class FileDataService {
|
||||
|
||||
constructor(private songDataService: SongDataService) {
|
||||
}
|
||||
|
||||
public async put(songId: string, file: FileServer): Promise<string> {
|
||||
const songRef = this.songDataService.getSongRef(songId);
|
||||
const fileCollection = songRef.collection('files');
|
||||
const id = await fileCollection.add(file);
|
||||
return id.id;
|
||||
}
|
||||
|
||||
public get$(songId: string): Observable<File[]> {
|
||||
const songRef = this.songDataService.getSongRef(songId);
|
||||
return songRef.collection<File>('files').snapshotChanges().pipe(map(actions => {
|
||||
return actions.map(a => ({
|
||||
...a.payload.doc.data(),
|
||||
id: a.payload.doc.id
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
5
src/app/modules/songs/services/file.ts
Normal file
5
src/app/modules/songs/services/file.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import {FileServer} from './fileServer';
|
||||
|
||||
export interface File extends FileServer {
|
||||
id: string;
|
||||
}
|
||||
5
src/app/modules/songs/services/fileBase.ts
Normal file
5
src/app/modules/songs/services/fileBase.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export class FileBase {
|
||||
|
||||
protected basePath = '/attachments';
|
||||
protected directory = (songId: string) => `${this.basePath}/${songId}`;
|
||||
}
|
||||
5
src/app/modules/songs/services/fileServer.ts
Normal file
5
src/app/modules/songs/services/fileServer.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface FileServer {
|
||||
name: string;
|
||||
path: string;
|
||||
createdAt: Date;
|
||||
}
|
||||
41
src/app/modules/songs/services/song-data.service.spec.ts
Normal file
41
src/app/modules/songs/services/song-data.service.spec.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import {async, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {SongDataService} from './song-data.service';
|
||||
import {AngularFirestore} from '@angular/fire/firestore';
|
||||
import {of} from 'rxjs';
|
||||
|
||||
describe('SongDataService', () => {
|
||||
|
||||
const songs = [
|
||||
{title: 'title1'}
|
||||
];
|
||||
|
||||
const angularFirestoreCollection = {
|
||||
valueChanges: () => of(songs)
|
||||
};
|
||||
|
||||
const mockAngularFirestore = {
|
||||
collection: () => angularFirestoreCollection
|
||||
};
|
||||
|
||||
beforeEach(() => TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{provide: AngularFirestore, useValue: mockAngularFirestore}
|
||||
]
|
||||
}));
|
||||
|
||||
it('should be created', () => {
|
||||
const service: SongDataService = TestBed.get(SongDataService);
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should list songs', async(() => {
|
||||
const service: SongDataService = TestBed.get(SongDataService);
|
||||
service.list().subscribe(s => {
|
||||
expect(s).toEqual([
|
||||
{title: 'title1'}
|
||||
] as any);
|
||||
}
|
||||
);
|
||||
}));
|
||||
});
|
||||
40
src/app/modules/songs/services/song-data.service.ts
Normal file
40
src/app/modules/songs/services/song-data.service.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {AngularFirestore, AngularFirestoreCollection} from '@angular/fire/firestore';
|
||||
import {Song} from '../models/song';
|
||||
import {Observable} from 'rxjs';
|
||||
import {map} from 'rxjs/operators';
|
||||
import {AngularFirestoreDocument} from '@angular/fire/firestore/document/document';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SongDataService {
|
||||
private songCollection: AngularFirestoreCollection<Song>;
|
||||
private readonly songs: Observable<Song[]>;
|
||||
|
||||
constructor(private afs: AngularFirestore) {
|
||||
this.songCollection = afs.collection<Song>('songs');
|
||||
this.songs = this.songCollection.snapshotChanges().pipe(map(actions => {
|
||||
return actions.map(a => ({
|
||||
...a.payload.doc.data(),
|
||||
id: a.payload.doc.id
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
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> {
|
||||
return this.getSongRef(songId).valueChanges().pipe(map(song => ({
|
||||
...song,
|
||||
id: songId
|
||||
} as Song)));
|
||||
}
|
||||
|
||||
public async update(songId: string, data: any): Promise<void> {
|
||||
await this.getSongRef(songId).update(data);
|
||||
}
|
||||
}
|
||||
|
||||
36
src/app/modules/songs/services/song.service.spec.ts
Normal file
36
src/app/modules/songs/services/song.service.spec.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import {async, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {SongService} from './song.service';
|
||||
import {SongDataService} from './song-data.service';
|
||||
import {of} from 'rxjs';
|
||||
|
||||
describe('SongService', () => {
|
||||
|
||||
const songs = [
|
||||
{title: 'title1'}
|
||||
];
|
||||
|
||||
const mockSongDataService = {
|
||||
list: () => of(songs)
|
||||
};
|
||||
|
||||
beforeEach(() => TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{provide: SongDataService, useValue: mockSongDataService}
|
||||
]
|
||||
}));
|
||||
|
||||
it('should be created', () => {
|
||||
const service: SongService = TestBed.get(SongService);
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should list songs', async(() => {
|
||||
const service: SongService = TestBed.get(SongService);
|
||||
service.list$().subscribe(s => {
|
||||
expect(s).toEqual([
|
||||
{title: 'title1'}
|
||||
] as any);
|
||||
});
|
||||
}));
|
||||
});
|
||||
61
src/app/modules/songs/services/song.service.ts
Normal file
61
src/app/modules/songs/services/song.service.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {Observable} from 'rxjs';
|
||||
import {Song} from '../models/song';
|
||||
import {SongDataService} from './song-data.service';
|
||||
import {tap} from 'rxjs/operators';
|
||||
|
||||
declare var importCCLI: any;
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SongService {
|
||||
|
||||
public TYPES = ['Praise', 'Worship'];
|
||||
|
||||
public LEGAL_OWNER = ['CCLI', 'other'];
|
||||
public LEGAL_TYPE = ['open', 'allowed'];
|
||||
|
||||
public KEYS = [
|
||||
'C', 'C#', 'Db', 'D', 'D#', 'Eb', 'E', 'F', 'F#', 'Gb', 'G', 'G#', 'Ab', 'A', 'A#', 'B', 'H',
|
||||
'c', 'c#', 'db', 'd', 'd#', 'eb', 'e', 'f', 'f#', 'gb', 'g', 'g#', 'ab', 'a', 'a#', 'b', 'h'
|
||||
];
|
||||
private list: Song[];
|
||||
|
||||
constructor(private songDataService: SongDataService) {
|
||||
importCCLI = (songs: Song[]) => this.updateFromCLI(songs);
|
||||
}
|
||||
|
||||
public list$ = (): Observable<Song[]> => this.songDataService.list().pipe(tap(_ => this.list = _));
|
||||
public read = (songId: string): Observable<Song | undefined> => this.songDataService.read(songId);
|
||||
|
||||
public async update(songId: string, data: any): Promise<void> {
|
||||
await this.songDataService.update(songId, data);
|
||||
}
|
||||
|
||||
// https://www.csvjson.com/csv2json
|
||||
private async updateFromCLI(songs: Song[]) {
|
||||
const mapped = songs.map(_ => ({
|
||||
number: _.number,
|
||||
legalType: _.legalType === 'ja' ? 'allowed' : 'open',
|
||||
legalOwner: _.legalOwner === 'ja' ? 'CCLI' : 'other',
|
||||
title: _.title,
|
||||
legalOwnerId: _.legalOwnerId,
|
||||
origin: _.origin,
|
||||
artist: _.artist,
|
||||
comment: _.comment
|
||||
}));
|
||||
const promises = this.list.map(async _ => {
|
||||
// tslint:disable-next-line:triple-equals
|
||||
const mappedSongs = mapped.filter(f => f.number == _.number);
|
||||
if (mappedSongs.length === 1) {
|
||||
const mappedSong = mappedSongs[0];
|
||||
const id = _.id;
|
||||
return await this.update(id, mappedSong);
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
|
||||
import {TextRenderingService} from './text-rendering.service';
|
||||
|
||||
describe('TextRenderingService', () => {
|
||||
beforeEach(() => TestBed.configureTestingModule({}));
|
||||
|
||||
it('should be created', () => {
|
||||
const service: TextRenderingService = TestBed.get(TextRenderingService);
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
45
src/app/modules/songs/services/text-rendering.service.ts
Normal file
45
src/app/modules/songs/services/text-rendering.service.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
export enum SectionType {
|
||||
Verse,
|
||||
Chorus,
|
||||
Bridge,
|
||||
}
|
||||
|
||||
export enum LineType {
|
||||
title,
|
||||
chrod,
|
||||
text,
|
||||
}
|
||||
|
||||
export interface Line {
|
||||
type: LineType;
|
||||
text: string;
|
||||
}
|
||||
|
||||
|
||||
export interface Section {
|
||||
type: SectionType;
|
||||
number: number;
|
||||
lines: Line[];
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TextRenderingService {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
public render(text: string): Section[] {
|
||||
const lines = text.match(/[^\r\n]+/g);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private findSection(line: string) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
12
src/app/modules/songs/services/upload.service.spec.ts
Normal file
12
src/app/modules/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();
|
||||
});
|
||||
});
|
||||
60
src/app/modules/songs/services/upload.service.ts
Normal file
60
src/app/modules/songs/services/upload.service.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
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 {FileBase} from './fileBase';
|
||||
import {FileServer} from './fileServer';
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UploadService extends FileBase {
|
||||
|
||||
constructor(private fileDataService: FileDataService, private angularFireStorage: AngularFireStorage) {
|
||||
super();
|
||||
}
|
||||
|
||||
public async pushUpload(songId: string, upload: Upload) {
|
||||
const directory = this.directory(songId);
|
||||
const filePath = `${directory}/${upload.file.name}`;
|
||||
upload.path = directory;
|
||||
|
||||
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: FileServer = {
|
||||
name: upload.file.name,
|
||||
path: upload.path,
|
||||
createdAt: new Date()
|
||||
};
|
||||
await this.fileDataService.put(songId, file);
|
||||
}
|
||||
}
|
||||
13
src/app/modules/songs/services/upload.ts
Normal file
13
src/app/modules/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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user