diff --git a/WEB/.firebaserc b/WEB/.firebaserc new file mode 100644 index 0000000..78eef2b --- /dev/null +++ b/WEB/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "worshipgenerator" + } +} diff --git a/WEB/.gitignore b/WEB/.gitignore new file mode 100644 index 0000000..f626852 --- /dev/null +++ b/WEB/.gitignore @@ -0,0 +1,65 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +firebase-debug.log* + +# Firebase cache +.firebase/ + +# Firebase config + +# Uncomment this if you'd like others to create their own Firebase project. +# For a team working on the same Firebase project(s), it is recommended to leave +# it commented so all members can deploy to the same project(s) in .firebaserc. +# .firebaserc + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env diff --git a/WEB/firebase.json b/WEB/firebase.json new file mode 100644 index 0000000..2f1e0ff --- /dev/null +++ b/WEB/firebase.json @@ -0,0 +1,11 @@ +{ + "hosting": { + "public": "dist/wgenerator", + "rewrites": [ + { + "source": "**", + "destination": "/index.html" + } + ] + } +} diff --git a/WEB/package.json b/WEB/package.json index 096be09..f91a3e9 100644 --- a/WEB/package.json +++ b/WEB/package.json @@ -3,6 +3,7 @@ "version": "0.0.0", "scripts": { "ng": "ng", + "deploy": "ng build --prod && firebase deploy", "start": "ng serve", "build": "ng build", "test": "ng test", diff --git a/WEB/src/app/data/ODataBaseService.ts b/WEB/src/app/data/ODataBaseService.ts index bc2c8e6..7ece930 100644 --- a/WEB/src/app/data/ODataBaseService.ts +++ b/WEB/src/app/data/ODataBaseService.ts @@ -1,20 +1,27 @@ import {Expand, ODataQuery, ODataService} from 'odata-v4-ng'; import {Observable} from 'rxjs'; import {map, tap} from 'rxjs/operators'; -import {base} from './urls'; +import {environment} from '../../environments/environment'; export class ODataBaseService { - private url: string; + private readonly url: string; constructor(private odataService: ODataService, private entity: string) { - this.url = base + '/odata/'; + this.url = `${environment.api}/odata/`; } - public list$(properties: string[]): Observable { + public list$(properties: string[], skip: number = null, top: number = null): Observable<{ count: number, data: TResponse[] }> { const query = new ODataQuery(this.odataService, this.url) .entitySet(this.entity) + .countOption(true) + .skip(skip) + .top(top) .select(properties); - const get = query.get().pipe(map(_ => _.toPropertyValue())); + + const get = query.get().pipe(map(_ => ({ + count: _.getBodyAsJson()['@odata.count'], + data: _.toPropertyValue() + }))); return get; } diff --git a/WEB/src/app/data/edit-song.service.ts b/WEB/src/app/data/edit-song.service.ts index 0174c89..c7e8961 100644 --- a/WEB/src/app/data/edit-song.service.ts +++ b/WEB/src/app/data/edit-song.service.ts @@ -95,7 +95,7 @@ export class EditSongService { private firstFreeNumber(): number { let number = 0; - const numbers = this.songsService.songs.value.map(_ => _.Number); + const numbers = this.songsService.songs.value.data.map(_ => _.Number); while (numbers.indexOf(++number) !== -1) { } return number; diff --git a/WEB/src/app/data/songs.service.ts b/WEB/src/app/data/songs.service.ts index cdbacdb..1efef3f 100644 --- a/WEB/src/app/data/songs.service.ts +++ b/WEB/src/app/data/songs.service.ts @@ -6,8 +6,8 @@ import {Song} from '../songs/models/song.model'; import {BehaviorSubject, Observable} from 'rxjs'; import {tap} from 'rxjs/operators'; import {State} from './state'; -import {base} from './urls'; import {FileType} from '../songs/models/files-types.model'; +import {environment} from '../../environments/environment'; @Injectable({ providedIn: 'root' @@ -15,26 +15,25 @@ import {FileType} from '../songs/models/files-types.model'; export class SongsService extends ODataBaseService { public state = new BehaviorSubject(State.list); - public songs: BehaviorSubject = new BehaviorSubject([]); + public songs = new BehaviorSubject<{ count: number, data: Song[] }>({count: 0, data: []}); constructor(odataService: ODataService, private httpClient: HttpClient) { super(odataService, 'songs'); } - public loadSongList$(): Observable { + public loadSongList$(page: number, pageSize: number): Observable<{ count: number, data: Song[] }> { const properties = ['ID', 'Name', 'Number', 'SongType', 'Key', 'Tempo']; - const list = this.list$(properties).pipe( + const list = this.list$(properties, page * pageSize, pageSize).pipe( tap(_ => this.songs.next(_)) ); return list; } - public patch$(id: number, control: string, value: any): Observable { const patch = super.patch$(id, control, value).pipe( tap(() => { const songs = this.songs.value; - const song = songs.filter(_ => _.ID === id)[0]; + const song = songs.data.filter(_ => _.ID === id)[0]; song[control] = value; this.songs.next(songs); }) @@ -55,7 +54,7 @@ export class SongsService extends ODataBaseService { name: string, fileType: FileType ): Observable { - const url = `${base}/api/songs/${songId}/files/${fileId}/edit?Name=${name}&FileType=${fileType}`; + const url = `${environment.api}/api/songs/${songId}/files/${fileId}/edit?Name=${name}&FileType=${fileType}`; const get = this.httpClient.get(url); return get; } @@ -64,7 +63,7 @@ export class SongsService extends ODataBaseService { songId: number, fileId: number ): Observable { - const url = `${base}/api/songs/${songId}/files/${fileId}/delete`; + const url = `${environment.api}/api/songs/${songId}/files/${fileId}/delete`; const get = this.httpClient.get(url); return get; } diff --git a/WEB/src/app/data/urls.ts b/WEB/src/app/data/urls.ts deleted file mode 100644 index 0214ac7..0000000 --- a/WEB/src/app/data/urls.ts +++ /dev/null @@ -1,2 +0,0 @@ -// export const base = 'http://192.168.178.20/API'; -export const base = 'http://test.benjamin-ifland.de'; diff --git a/WEB/src/app/songs/components/songs/songs.component.ts b/WEB/src/app/songs/components/songs/songs.component.ts index 73d2267..e217690 100644 --- a/WEB/src/app/songs/components/songs/songs.component.ts +++ b/WEB/src/app/songs/components/songs/songs.component.ts @@ -13,6 +13,6 @@ export class SongsComponent { constructor( public songsService: SongsService ) { - songsService.loadSongList$().subscribe(); + songsService.loadSongList$(0, 15).subscribe(); } } diff --git a/WEB/src/app/songs/components/songs/table/table.component.html b/WEB/src/app/songs/components/songs/table/table.component.html index 22e0849..aad092f 100644 --- a/WEB/src/app/songs/components/songs/table/table.component.html +++ b/WEB/src/app/songs/components/songs/table/table.component.html @@ -13,7 +13,7 @@ @@ -72,4 +72,5 @@ >
+ diff --git a/WEB/src/app/songs/components/songs/table/table.component.ts b/WEB/src/app/songs/components/songs/table/table.component.ts index 5c4dcbf..407deae 100644 --- a/WEB/src/app/songs/components/songs/table/table.component.ts +++ b/WEB/src/app/songs/components/songs/table/table.component.ts @@ -1,9 +1,10 @@ import {SongsService} from '../../../../data/songs.service'; -import {ChangeDetectionStrategy, ChangeDetectorRef, Component} from '@angular/core'; +import {AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ViewChild} from '@angular/core'; import {State} from 'src/app/data/state'; import {faFileMedical} from '@fortawesome/free-solid-svg-icons'; import {Observable} from 'rxjs'; -import {map} from 'rxjs/operators'; +import {map, switchMap} from 'rxjs/operators'; +import {MatPaginator} from '@angular/material'; @Component({ selector: 'app-table', @@ -11,18 +12,28 @@ import {map} from 'rxjs/operators'; styleUrls: ['./table.component.less'], changeDetection: ChangeDetectionStrategy.OnPush }) -export class TableComponent { +export class TableComponent implements AfterViewInit { public State = State; public faNew = faFileMedical; public columnsFull = ['Number', 'Name', 'Key', 'SongType', 'Tempo']; public columnsPinned = ['Number', 'Name']; + @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator; + constructor( public songsService: SongsService, - private change: ChangeDetectorRef + private ref: ChangeDetectorRef ) { } + public ngAfterViewInit(): void { + this.paginator.page.pipe( + switchMap(_ => this.songsService.loadSongList$(_.pageIndex, _.pageSize)) + ).subscribe(() => { + this.ref.markForCheck(); + }); + } + public get columns(): Observable { return this.songsService.state.pipe(map(_ => _ === State.list ? this.columnsFull : this.columnsPinned)); } diff --git a/WEB/src/app/songs/services/fileupload.factory.ts b/WEB/src/app/songs/services/fileupload.factory.ts index b573155..155c19b 100644 --- a/WEB/src/app/songs/services/fileupload.factory.ts +++ b/WEB/src/app/songs/services/fileupload.factory.ts @@ -1,6 +1,6 @@ -import {base} from '../../data/urls'; import {Injectable} from '@angular/core'; import {FileUploader} from 'ng2-file-upload'; +import {environment} from '../../../environments/environment'; @Injectable({ providedIn: 'root' @@ -8,7 +8,7 @@ import {FileUploader} from 'ng2-file-upload'; export class FileuploadFactory { public static provideForNewFiles(songId: number): FileUploader { const uploader = new FileUploader({ - url: `${base}/api/songs/${songId}/files`, + url: `${environment.api}/api/songs/${songId}/files`, autoUpload: true, isHTML5: true }); diff --git a/WEB/src/app/songs/songs.module.ts b/WEB/src/app/songs/songs.module.ts index f7dd546..e8edd33 100644 --- a/WEB/src/app/songs/songs.module.ts +++ b/WEB/src/app/songs/songs.module.ts @@ -5,7 +5,7 @@ import {SongsRoutingModule} from './songs-routing.module'; import {SongsComponent} from './components/songs/songs.component'; import {TableComponent} from './components/songs/table/table.component'; import {FontAwesomeModule} from '@fortawesome/angular-fontawesome'; -import {MatButtonModule, MatChipsModule, MatTableModule} from '@angular/material'; +import {MatButtonModule, MatChipsModule, MatPaginatorModule, MatTableModule} from '@angular/material'; @NgModule({ @@ -17,7 +17,8 @@ import {MatButtonModule, MatChipsModule, MatTableModule} from '@angular/material MatTableModule, MatChipsModule, - MatButtonModule + MatButtonModule, + MatPaginatorModule ] }) export class SongsModule { diff --git a/WEB/src/environments/environment.prod.ts b/WEB/src/environments/environment.prod.ts index 5d08331..4da1305 100644 --- a/WEB/src/environments/environment.prod.ts +++ b/WEB/src/environments/environment.prod.ts @@ -1,3 +1,4 @@ export const environment = { - production: true + production: true, + api: 'https://test.benjamin-ifland.de' }; diff --git a/WEB/src/environments/environment.ts b/WEB/src/environments/environment.ts index 6b32308..1a0052d 100644 --- a/WEB/src/environments/environment.ts +++ b/WEB/src/environments/environment.ts @@ -3,7 +3,8 @@ // The list of file replacements can be found in `angular.json`. export const environment = { - production: false + production: false, + api: 'http://test.benjamin-ifland.de' }; /*