Merge branch 'develop' of https://git.wmi.amu.edu.pl/s434776/PRI_2020-FE into develop
This commit is contained in:
commit
e609b58ac9
24
frontend/package-lock.json
generated
24
frontend/package-lock.json
generated
@ -2921,6 +2921,30 @@
|
|||||||
"intersection-observer": "0.7.0"
|
"intersection-observer": "0.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@ngrx/effects": {
|
||||||
|
"version": "10.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-10.0.1.tgz",
|
||||||
|
"integrity": "sha512-pw0hRQNlyBBRHH1NRWl3TF+RtEAS4XOSnoTHPtQ84Ib/bEribvexsdEq3k6yLWvR3tLTudb5J6SYwYawcM6omA==",
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@ngrx/store": {
|
||||||
|
"version": "10.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ngrx/store/-/store-10.0.1.tgz",
|
||||||
|
"integrity": "sha512-ZbPvhp/tRYnS3jZ28mDOX2LH3jfySXT0uv8ffIboM/o9QxBGHpAJyBct2zkpy4duYBc3i/sIbRn+CEpAjLXjHw==",
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@ngrx/store-devtools": {
|
||||||
|
"version": "10.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ngrx/store-devtools/-/store-devtools-10.0.1.tgz",
|
||||||
|
"integrity": "sha512-kwgF1yjjVn0FER+AG83OLCYSMuX4/E3L+DN4doSoZs4BNO9FdkYIIA4ul1nXT5d6SLiFFTmlufmbgc6HCF3pjQ==",
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@ngtools/webpack": {
|
"@ngtools/webpack": {
|
||||||
"version": "10.0.0",
|
"version": "10.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-10.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-10.0.0.tgz",
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
"@angular/router": "~10.0.0",
|
"@angular/router": "~10.0.0",
|
||||||
"@nebular/eva-icons": "5.0.0",
|
"@nebular/eva-icons": "5.0.0",
|
||||||
"@nebular/theme": "^5.0.0",
|
"@nebular/theme": "^5.0.0",
|
||||||
|
"@ngrx/effects": "^10.0.1",
|
||||||
|
"@ngrx/store": "^10.0.1",
|
||||||
|
"@ngrx/store-devtools": "^10.0.1",
|
||||||
"@types/papaparse": "^5.0.3",
|
"@types/papaparse": "^5.0.3",
|
||||||
"d3": "^5.16.0",
|
"d3": "^5.16.0",
|
||||||
"eva-icons": "^1.1.2",
|
"eva-icons": "^1.1.2",
|
||||||
|
@ -6,7 +6,7 @@ import { Observable } from 'rxjs';
|
|||||||
export class SendDataService {
|
export class SendDataService {
|
||||||
constructor(private http: HttpClient) {}
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
postFile(file: File): Observable<File> {
|
postFile(file: File): Observable<any> {
|
||||||
const formData: FormData = new FormData();
|
const formData: FormData = new FormData();
|
||||||
const requestOptions = {
|
const requestOptions = {
|
||||||
responseType: 'text' as 'json',
|
responseType: 'text' as 'json',
|
||||||
|
18
frontend/src/app/actions/front-page.actions.ts
Normal file
18
frontend/src/app/actions/front-page.actions.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
|
import { createAction, props } from '@ngrx/store';
|
||||||
|
|
||||||
|
export const fetchFile = createAction(
|
||||||
|
'[FrontPage Component] Fetch File',
|
||||||
|
props<{ file: File }>()
|
||||||
|
);
|
||||||
|
export const sendFile = createAction('[FrontPage Component] Send File');
|
||||||
|
|
||||||
|
export const sendFileError = createAction(
|
||||||
|
'[FrontPage Component] Send Error',
|
||||||
|
props<{ error: HttpErrorResponse }>()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const sendFileSuccess = createAction(
|
||||||
|
'[FrontPage Component] Send Success',
|
||||||
|
props<{ data: string }>()
|
||||||
|
);
|
@ -18,6 +18,10 @@ import {
|
|||||||
import { FrontPageModule } from './front-page/front-page.module';
|
import { FrontPageModule } from './front-page/front-page.module';
|
||||||
import { SharedDataService } from './_services/shared-data.service';
|
import { SharedDataService } from './_services/shared-data.service';
|
||||||
import { SidebarItemsService } from './_services/sidebar-items.service';
|
import { SidebarItemsService } from './_services/sidebar-items.service';
|
||||||
|
import { StoreModule } from '@ngrx/store';
|
||||||
|
import { reducers, metaReducers } from './reducers';
|
||||||
|
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||||
|
import { EffectsModule } from '@ngrx/effects';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [AppComponent],
|
declarations: [AppComponent],
|
||||||
@ -32,6 +36,11 @@ import { SidebarItemsService } from './_services/sidebar-items.service';
|
|||||||
NbEvaIconsModule,
|
NbEvaIconsModule,
|
||||||
FrontPageModule,
|
FrontPageModule,
|
||||||
NbToastrModule.forRoot(),
|
NbToastrModule.forRoot(),
|
||||||
|
StoreModule.forRoot(reducers, {
|
||||||
|
metaReducers,
|
||||||
|
}),
|
||||||
|
StoreDevtoolsModule.instrument({ maxAge: 25 }),
|
||||||
|
EffectsModule.forRoot([]),
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
providers: [SharedDataService, NbSidebarService, SidebarItemsService],
|
providers: [SharedDataService, NbSidebarService, SidebarItemsService],
|
||||||
|
71
frontend/src/app/effects/front-page.effects.ts
Normal file
71
frontend/src/app/effects/front-page.effects.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { SendDataService } from '../_services/send-data.service';
|
||||||
|
import * as FrontPageActions from '../actions/front-page.actions';
|
||||||
|
import * as FrontPageSelectors from '../selectors/front-page.selectors';
|
||||||
|
import { Actions, ofType, createEffect } from '@ngrx/effects';
|
||||||
|
import { State as AppState } from '../reducers/index';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import {
|
||||||
|
exhaustMap,
|
||||||
|
withLatestFrom,
|
||||||
|
tap,
|
||||||
|
map,
|
||||||
|
catchError,
|
||||||
|
concatMap,
|
||||||
|
flatMap,
|
||||||
|
} from 'rxjs/operators';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { NbToastrService } from '@nebular/theme';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FrontPageEffect {
|
||||||
|
constructor(
|
||||||
|
private sendDataService: SendDataService,
|
||||||
|
private actions$: Actions,
|
||||||
|
private store$: Store<AppState>,
|
||||||
|
private toastService: NbToastrService,
|
||||||
|
private router: Router
|
||||||
|
) {}
|
||||||
|
|
||||||
|
file$ = createEffect(() =>
|
||||||
|
this.actions$.pipe(
|
||||||
|
ofType(FrontPageActions.sendFile),
|
||||||
|
concatMap((action) =>
|
||||||
|
of(action).pipe(
|
||||||
|
withLatestFrom(this.store$.select(FrontPageSelectors.selectFile))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
flatMap(([_, file]) =>
|
||||||
|
this.sendDataService.postFile(file).pipe(
|
||||||
|
map((result) => FrontPageActions.sendFileSuccess({ data: result })),
|
||||||
|
catchError((error) => of(FrontPageActions.sendFileError({ error })))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
toast$ = createEffect(
|
||||||
|
() =>
|
||||||
|
this.actions$.pipe(
|
||||||
|
ofType(FrontPageActions.sendFileError),
|
||||||
|
tap(({ error }) => {
|
||||||
|
if (error.status === 406) {
|
||||||
|
this.toastService.danger('', 'Format pliku jest niepoprawny!', {
|
||||||
|
icon: 'alert-circle',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
|
{ dispatch: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
navigate$ = createEffect(
|
||||||
|
() =>
|
||||||
|
this.actions$.pipe(
|
||||||
|
ofType(FrontPageActions.sendFileSuccess),
|
||||||
|
tap(() => this.router.navigate(['/view']))
|
||||||
|
),
|
||||||
|
{ dispatch: false }
|
||||||
|
);
|
||||||
|
}
|
@ -41,12 +41,12 @@
|
|||||||
nbButton
|
nbButton
|
||||||
status="success"
|
status="success"
|
||||||
(click)="sendFile($event)"
|
(click)="sendFile($event)"
|
||||||
[disabled]="!isFileFetched"
|
[disabled]="!(isFileFetched$ | async)"
|
||||||
>
|
>
|
||||||
Wyślij!
|
Wyślij!
|
||||||
</button>
|
</button>
|
||||||
<p *ngIf="fileName">
|
<p *ngIf="fileName$ | async">
|
||||||
<nb-icon icon="file-add-outline"></nb-icon> {{ fileName }}
|
<nb-icon icon="file-add-outline"></nb-icon> {{ fileName$ | async }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -1,27 +1,26 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Store } from '@ngrx/store';
|
||||||
import { SendDataService } from '../_services/send-data.service';
|
import { State } from '../reducers/index';
|
||||||
import { SharedDataService } from '../_services/shared-data.service';
|
import { Observable } from 'rxjs';
|
||||||
import { HttpErrorResponse } from '@angular/common/http';
|
import * as Selectors from '../selectors/front-page.selectors';
|
||||||
import { NbToastrService } from '@nebular/theme';
|
import { fetchFile, sendFile } from '../actions/front-page.actions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-front-page',
|
selector: 'app-front-page',
|
||||||
templateUrl: './front-page.component.html',
|
templateUrl: './front-page.component.html',
|
||||||
styleUrls: ['./front-page.component.scss'],
|
styleUrls: ['./front-page.component.scss'],
|
||||||
})
|
})
|
||||||
export class FrontPageComponent {
|
export class FrontPageComponent implements OnInit {
|
||||||
private file: File;
|
file$: Observable<File>;
|
||||||
public fileName: string;
|
fileName$: Observable<string>;
|
||||||
public isFileFetched: boolean;
|
isFileFetched$: Observable<boolean>;
|
||||||
|
|
||||||
constructor(
|
constructor(private store: Store<State>) {}
|
||||||
private sendDataService: SendDataService,
|
|
||||||
private sharedDataService: SharedDataService,
|
ngOnInit() {
|
||||||
private router: Router,
|
this.file$ = this.store.select(Selectors.selectFile);
|
||||||
private toastService: NbToastrService
|
this.fileName$ = this.store.select(Selectors.selectFileName);
|
||||||
) {
|
this.isFileFetched$ = this.store.select(Selectors.selectFetchStatus);
|
||||||
this.isFileFetched = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollTo(el: HTMLElement) {
|
scrollTo(el: HTMLElement) {
|
||||||
@ -38,24 +37,10 @@ export class FrontPageComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetchFile(event: any): void {
|
fetchFile(event: any): void {
|
||||||
this.file = event.target.files[0];
|
this.store.dispatch(fetchFile({ file: event.target.files[0] }));
|
||||||
this.fileName = this.file.name;
|
|
||||||
this.isFileFetched = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sendFile(event: any): void {
|
sendFile(event: any): void {
|
||||||
this.sendDataService.postFile(this.file).subscribe(
|
this.store.dispatch({ type: '[FrontPage Component] Send File' });
|
||||||
(res: any) => {
|
|
||||||
this.sharedDataService.setData(res);
|
|
||||||
this.router.navigate(['/view']);
|
|
||||||
},
|
|
||||||
(error: HttpErrorResponse) => {
|
|
||||||
if (error.status === 406) {
|
|
||||||
this.toastService.danger('', 'Format pliku jest niepoprawny!', {
|
|
||||||
icon: 'alert-circle',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ import {
|
|||||||
NbIconModule,
|
NbIconModule,
|
||||||
NbStepperModule,
|
NbStepperModule,
|
||||||
} from '@nebular/theme';
|
} from '@nebular/theme';
|
||||||
|
import { EffectsModule } from '@ngrx/effects';
|
||||||
|
import { FrontPageEffect } from '../effects/front-page.effects';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [FrontPageComponent],
|
declarations: [FrontPageComponent],
|
||||||
@ -19,6 +21,7 @@ import {
|
|||||||
NbCardModule,
|
NbCardModule,
|
||||||
NbIconModule,
|
NbIconModule,
|
||||||
NbStepperModule,
|
NbStepperModule,
|
||||||
|
EffectsModule.forFeature([FrontPageEffect]),
|
||||||
],
|
],
|
||||||
providers: [SendDataService],
|
providers: [SendDataService],
|
||||||
})
|
})
|
||||||
|
46
frontend/src/app/reducers/front-page.reducers.ts
Normal file
46
frontend/src/app/reducers/front-page.reducers.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { Action, createReducer, on } from '@ngrx/store';
|
||||||
|
import * as Actions from '../actions/front-page.actions';
|
||||||
|
|
||||||
|
export interface State {
|
||||||
|
file: File;
|
||||||
|
fileName: string;
|
||||||
|
isFileFetched: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DataState {
|
||||||
|
data: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialState: State = {
|
||||||
|
file: {} as File,
|
||||||
|
fileName: '',
|
||||||
|
isFileFetched: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const initialDataState: DataState = {
|
||||||
|
data: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const _fileReducer = createReducer(
|
||||||
|
initialState,
|
||||||
|
on(Actions.fetchFile, (_, { file }) => ({
|
||||||
|
file: file,
|
||||||
|
fileName: file.name,
|
||||||
|
isFileFetched: true,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
const _dataReducer = createReducer(
|
||||||
|
initialDataState,
|
||||||
|
on(Actions.sendFileSuccess, (_, { data }) => {
|
||||||
|
return { data: data };
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
export function fileReducer(state: State | undefined, action: Action) {
|
||||||
|
return _fileReducer(state, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dataReducer(state: DataState | undefined, action: Action) {
|
||||||
|
return _dataReducer(state, action);
|
||||||
|
}
|
31
frontend/src/app/reducers/index.ts
Normal file
31
frontend/src/app/reducers/index.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { ActionReducer, ActionReducerMap, MetaReducer } from '@ngrx/store';
|
||||||
|
import { environment } from '../../environments/environment';
|
||||||
|
import {
|
||||||
|
fileReducer,
|
||||||
|
State as FileState,
|
||||||
|
DataState,
|
||||||
|
dataReducer,
|
||||||
|
} from './front-page.reducers';
|
||||||
|
|
||||||
|
export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
|
||||||
|
return function (state, action) {
|
||||||
|
console.log('State: ', state);
|
||||||
|
console.log('Action: ', action);
|
||||||
|
|
||||||
|
return reducer(state, action);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface State {
|
||||||
|
fileState: FileState;
|
||||||
|
data: DataState;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const reducers: ActionReducerMap<State> = {
|
||||||
|
fileState: fileReducer,
|
||||||
|
data: dataReducer,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const metaReducers: MetaReducer<State>[] = !environment.production
|
||||||
|
? [debug]
|
||||||
|
: [];
|
22
frontend/src/app/selectors/front-page.selectors.ts
Normal file
22
frontend/src/app/selectors/front-page.selectors.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { createSelector, createFeatureSelector } from '@ngrx/store';
|
||||||
|
import { State as AppState } from '../reducers/index';
|
||||||
|
import { State as FileState } from '../reducers/front-page.reducers';
|
||||||
|
|
||||||
|
export const selectFeature = createFeatureSelector<AppState, FileState>(
|
||||||
|
'fileState'
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectFile = createSelector(
|
||||||
|
selectFeature,
|
||||||
|
(state: FileState) => state.file
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectFileName = createSelector(
|
||||||
|
selectFeature,
|
||||||
|
(state: FileState) => state.fileName
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectFetchStatus = createSelector(
|
||||||
|
selectFeature,
|
||||||
|
(state: FileState) => state.isFileFetched
|
||||||
|
);
|
Loading…
Reference in New Issue
Block a user