production settings

This commit is contained in:
2019-08-05 07:28:25 +02:00
parent 7bd42bda84
commit 1e9d111ceb
15 changed files with 129 additions and 28 deletions

5
WEB/.firebaserc Normal file
View File

@@ -0,0 +1,5 @@
{
"projects": {
"default": "worshipgenerator"
}
}

65
WEB/.gitignore vendored Normal file
View File

@@ -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

11
WEB/firebase.json Normal file
View File

@@ -0,0 +1,11 @@
{
"hosting": {
"public": "dist/wgenerator",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}

View File

@@ -3,6 +3,7 @@
"version": "0.0.0", "version": "0.0.0",
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"deploy": "ng build --prod && firebase deploy",
"start": "ng serve", "start": "ng serve",
"build": "ng build", "build": "ng build",
"test": "ng test", "test": "ng test",

View File

@@ -1,20 +1,27 @@
import {Expand, ODataQuery, ODataService} from 'odata-v4-ng'; import {Expand, ODataQuery, ODataService} from 'odata-v4-ng';
import {Observable} from 'rxjs'; import {Observable} from 'rxjs';
import {map, tap} from 'rxjs/operators'; import {map, tap} from 'rxjs/operators';
import {base} from './urls'; import {environment} from '../../environments/environment';
export class ODataBaseService { export class ODataBaseService {
private url: string; private readonly url: string;
constructor(private odataService: ODataService, private entity: string) { constructor(private odataService: ODataService, private entity: string) {
this.url = base + '/odata/'; this.url = `${environment.api}/odata/`;
} }
public list$<TResponse>(properties: string[]): Observable<TResponse[]> { public list$<TResponse>(properties: string[], skip: number = null, top: number = null): Observable<{ count: number, data: TResponse[] }> {
const query = new ODataQuery(this.odataService, this.url) const query = new ODataQuery(this.odataService, this.url)
.entitySet(this.entity) .entitySet(this.entity)
.countOption(true)
.skip(skip)
.top(top)
.select(properties); .select(properties);
const get = query.get().pipe(map(_ => _.toPropertyValue<TResponse[]>()));
const get = query.get().pipe(map(_ => ({
count: _.getBodyAsJson()['@odata.count'],
data: _.toPropertyValue<TResponse[]>()
})));
return get; return get;
} }

View File

@@ -95,7 +95,7 @@ export class EditSongService {
private firstFreeNumber(): number { private firstFreeNumber(): number {
let number = 0; 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) { while (numbers.indexOf(++number) !== -1) {
} }
return number; return number;

View File

@@ -6,8 +6,8 @@ import {Song} from '../songs/models/song.model';
import {BehaviorSubject, Observable} from 'rxjs'; import {BehaviorSubject, Observable} from 'rxjs';
import {tap} from 'rxjs/operators'; import {tap} from 'rxjs/operators';
import {State} from './state'; import {State} from './state';
import {base} from './urls';
import {FileType} from '../songs/models/files-types.model'; import {FileType} from '../songs/models/files-types.model';
import {environment} from '../../environments/environment';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -15,26 +15,25 @@ import {FileType} from '../songs/models/files-types.model';
export class SongsService extends ODataBaseService { export class SongsService extends ODataBaseService {
public state = new BehaviorSubject<State>(State.list); public state = new BehaviorSubject<State>(State.list);
public songs: BehaviorSubject<Song[]> = new BehaviorSubject<Song[]>([]); public songs = new BehaviorSubject<{ count: number, data: Song[] }>({count: 0, data: []});
constructor(odataService: ODataService, private httpClient: HttpClient) { constructor(odataService: ODataService, private httpClient: HttpClient) {
super(odataService, 'songs'); super(odataService, 'songs');
} }
public loadSongList$(): Observable<Song[]> { public loadSongList$(page: number, pageSize: number): Observable<{ count: number, data: Song[] }> {
const properties = ['ID', 'Name', 'Number', 'SongType', 'Key', 'Tempo']; const properties = ['ID', 'Name', 'Number', 'SongType', 'Key', 'Tempo'];
const list = this.list$<Song>(properties).pipe( const list = this.list$<Song>(properties, page * pageSize, pageSize).pipe(
tap(_ => this.songs.next(_)) tap(_ => this.songs.next(_))
); );
return list; return list;
} }
public patch$(id: number, control: string, value: any): Observable<boolean> { public patch$(id: number, control: string, value: any): Observable<boolean> {
const patch = super.patch$(id, control, value).pipe( const patch = super.patch$(id, control, value).pipe(
tap(() => { tap(() => {
const songs = this.songs.value; const songs = this.songs.value;
const song = songs.filter(_ => _.ID === id)[0]; const song = songs.data.filter(_ => _.ID === id)[0];
song[control] = value; song[control] = value;
this.songs.next(songs); this.songs.next(songs);
}) })
@@ -55,7 +54,7 @@ export class SongsService extends ODataBaseService {
name: string, name: string,
fileType: FileType fileType: FileType
): Observable<any> { ): Observable<any> {
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); const get = this.httpClient.get(url);
return get; return get;
} }
@@ -64,7 +63,7 @@ export class SongsService extends ODataBaseService {
songId: number, songId: number,
fileId: number fileId: number
): Observable<any> { ): Observable<any> {
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); const get = this.httpClient.get(url);
return get; return get;
} }

View File

@@ -1,2 +0,0 @@
// export const base = 'http://192.168.178.20/API';
export const base = 'http://test.benjamin-ifland.de';

View File

@@ -13,6 +13,6 @@ export class SongsComponent {
constructor( constructor(
public songsService: SongsService public songsService: SongsService
) { ) {
songsService.loadSongList$().subscribe(); songsService.loadSongList$(0, 15).subscribe();
} }
} }

View File

@@ -13,7 +13,7 @@
<fa-icon [icon]="faNew"></fa-icon> <fa-icon [icon]="faNew"></fa-icon>
</button> </button>
<table <table
[dataSource]="songsService.songs | async" [dataSource]="(songsService.songs | async).data"
class="mat-elevation-z8" class="mat-elevation-z8"
mat-table mat-table
> >
@@ -72,4 +72,5 @@
></tr> ></tr>
</table> </table>
</div> </div>
<mat-paginator [length]="(songsService.songs | async).count" [pageSize]="15"></mat-paginator>
</div> </div>

View File

@@ -1,9 +1,10 @@
import {SongsService} from '../../../../data/songs.service'; 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 {State} from 'src/app/data/state';
import {faFileMedical} from '@fortawesome/free-solid-svg-icons'; import {faFileMedical} from '@fortawesome/free-solid-svg-icons';
import {Observable} from 'rxjs'; import {Observable} from 'rxjs';
import {map} from 'rxjs/operators'; import {map, switchMap} from 'rxjs/operators';
import {MatPaginator} from '@angular/material';
@Component({ @Component({
selector: 'app-table', selector: 'app-table',
@@ -11,18 +12,28 @@ import {map} from 'rxjs/operators';
styleUrls: ['./table.component.less'], styleUrls: ['./table.component.less'],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class TableComponent { export class TableComponent implements AfterViewInit {
public State = State; public State = State;
public faNew = faFileMedical; public faNew = faFileMedical;
public columnsFull = ['Number', 'Name', 'Key', 'SongType', 'Tempo']; public columnsFull = ['Number', 'Name', 'Key', 'SongType', 'Tempo'];
public columnsPinned = ['Number', 'Name']; public columnsPinned = ['Number', 'Name'];
@ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;
constructor( constructor(
public songsService: SongsService, 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<string[]> { public get columns(): Observable<string[]> {
return this.songsService.state.pipe(map(_ => _ === State.list ? this.columnsFull : this.columnsPinned)); return this.songsService.state.pipe(map(_ => _ === State.list ? this.columnsFull : this.columnsPinned));
} }

View File

@@ -1,6 +1,6 @@
import {base} from '../../data/urls';
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {FileUploader} from 'ng2-file-upload'; import {FileUploader} from 'ng2-file-upload';
import {environment} from '../../../environments/environment';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -8,7 +8,7 @@ import {FileUploader} from 'ng2-file-upload';
export class FileuploadFactory { export class FileuploadFactory {
public static provideForNewFiles(songId: number): FileUploader { public static provideForNewFiles(songId: number): FileUploader {
const uploader = new FileUploader({ const uploader = new FileUploader({
url: `${base}/api/songs/${songId}/files`, url: `${environment.api}/api/songs/${songId}/files`,
autoUpload: true, autoUpload: true,
isHTML5: true isHTML5: true
}); });

View File

@@ -5,7 +5,7 @@ import {SongsRoutingModule} from './songs-routing.module';
import {SongsComponent} from './components/songs/songs.component'; import {SongsComponent} from './components/songs/songs.component';
import {TableComponent} from './components/songs/table/table.component'; import {TableComponent} from './components/songs/table/table.component';
import {FontAwesomeModule} from '@fortawesome/angular-fontawesome'; import {FontAwesomeModule} from '@fortawesome/angular-fontawesome';
import {MatButtonModule, MatChipsModule, MatTableModule} from '@angular/material'; import {MatButtonModule, MatChipsModule, MatPaginatorModule, MatTableModule} from '@angular/material';
@NgModule({ @NgModule({
@@ -17,7 +17,8 @@ import {MatButtonModule, MatChipsModule, MatTableModule} from '@angular/material
MatTableModule, MatTableModule,
MatChipsModule, MatChipsModule,
MatButtonModule MatButtonModule,
MatPaginatorModule
] ]
}) })
export class SongsModule { export class SongsModule {

View File

@@ -1,3 +1,4 @@
export const environment = { export const environment = {
production: true production: true,
api: 'https://test.benjamin-ifland.de'
}; };

View File

@@ -3,7 +3,8 @@
// The list of file replacements can be found in `angular.json`. // The list of file replacements can be found in `angular.json`.
export const environment = { export const environment = {
production: false production: false,
api: 'http://test.benjamin-ifland.de'
}; };
/* /*