import { Injectable } from '@angular/core'; import { ToastrService } from 'ngx-toastr'; import { Effect, Actions, ofType } from '@ngrx/effects'; import { Store } from '@ngrx/store'; import { of } from 'rxjs'; import { map, switchMap, withLatestFrom, catchError } from 'rxjs/operators'; import * as criteriaActions from '../../metamodel/action/criteria.action'; import * as searchActions from './search.action'; import * as fromSearch from './search.reducer'; import { SearchService } from './search.service'; import { BetweenCriterion, SearchMeta } from './model'; @Injectable() export class SearchEffects { constructor( private actions$: Actions, private searchService: SearchService, private toastr: ToastrService, private store$: Store<{search: fromSearch.State}> ) { } @Effect() loadDatasetAttributeListSuccessAction$ = this.actions$.pipe( ofType(criteriaActions.LOAD_DATASET_ATTRIBUTE_LIST_SUCCESS), switchMap((action: criteriaActions.LoadDatasetAttributeListSuccessAction) => { const outputList = action.payload .filter(attribute => attribute.selected && attribute.id_output_family) .map(attribute => attribute.id); const criteriaList = action.payload .filter(attribute => attribute.id_criteria_family && attribute.search_type && attribute.min) .map(attribute => { if (attribute.search_type === 'bw') { return new BetweenCriterion(attribute.id, attribute.min.toString(), attribute.max.toString()); } }); return [ new searchActions.UpdateDefaultOutputListAction(outputList), new searchActions.UpdateDefaultCriteriaListAction(criteriaList) ]; }) ); @Effect() updateDefaultOutputListAction$ = this.actions$.pipe( ofType(searchActions.UPDATE_DEFAULT_OUTPUT_LIST), withLatestFrom(this.store$), switchMap(([action, state]) => { if (state.search.outputList.length > 0) { return of({type: 'No Action'}); } else { const updateDefaultOutputListAction = action as searchActions.UpdateDefaultOutputListAction; return of(new searchActions.UpdateOutputListAction(updateDefaultOutputListAction.payload)); } }) ); @Effect() updateDefaultCriteriaListAction$ = this.actions$.pipe( ofType(searchActions.UPDATE_DEFAULT_CRITERIA_LIST), withLatestFrom(this.store$), switchMap(([action, state]) => { if (state.search.criteriaList.length > 0) { return of({type: 'No Action'}); } else { const updateDefaultCriteriaListAction = action as searchActions.UpdateDefaultCriteriaListAction; return of(new searchActions.UpdateCriteriaListAction(updateDefaultCriteriaListAction.payload)); } }) ); @Effect() retrieveMetaAction$ = this.actions$.pipe( ofType(searchActions.RETRIEVE_META), withLatestFrom(this.store$), switchMap(([action, state]) => { const query = state.search.datasetName + '?a=' + state.search.outputList.join(';') + '&c=' + state.search.criteriaList.map(criterion => criterion.getCriterionStr()).join(';'); return this.searchService.retrieveMeta(query).pipe( map((searchMeta: SearchMeta) => new searchActions.RetrieveMetaSuccessAction(searchMeta)), catchError(() => of(new searchActions.RetrieveMetaFailedAction())) ) }) ) @Effect({dispatch: false}) retrieveMetaFailedAction$ = this.actions$.pipe( ofType(searchActions.RETRIEVE_META_FAILED), map(_ => this.toastr.error('Loading Failed!', 'The search meta data loading failed')) ); @Effect() retrieveDataAction$ = this.actions$.pipe( ofType(searchActions.RETRIEVE_DATA), withLatestFrom(this.store$), switchMap(([action, state]) => { const retrieveDataAction = action as searchActions.RetrieveDataAction; const query = state.search.datasetName + '?a=' + state.search.outputList.join(';') + '&c=' + state.search.criteriaList.map(criterion => criterion.getCriterionStr()).join(';') + '&p=10:' + retrieveDataAction.payload; return this.searchService.retrieveData(query).pipe( map((searchData: any[]) => new searchActions.RetrieveDataSuccessAction(searchData)), catchError(() => of(new searchActions.RetrieveDataFailedAction())) ) }) ) @Effect({dispatch: false}) retrieveDataFailedAction$ = this.actions$.pipe( ofType(searchActions.RETRIEVE_DATA_FAILED), map(_ => this.toastr.error('Loading Failed!', 'The search data loading failed')) ); }