From 773b7f679388dc977f6368a4ffe4bfd646c9376a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Agneray?= <francois.agneray@lam.fr> Date: Thu, 2 Sep 2021 17:40:32 +0200 Subject: [PATCH] Search multiple => WIP 2 --- .../app/instance/instance-routing.module.ts | 1 + client/src/app/instance/instance.reducer.ts | 3 + .../progress-bar-multiple.component.html | 19 ++--- .../progress-bar-multiple.component.ts | 8 +- .../summary-multiple.component.html | 14 ++-- .../components/summary-multiple.component.ts | 18 ++--- .../abstract-search-multiple.component.ts | 46 +++++++++++ .../containers/position.component.html | 32 +++----- .../containers/position.component.ts | 80 ++----------------- .../search-multiple-routing.module.ts | 2 +- .../search-multiple.component.html | 5 +- .../search-multiple.component.ts | 34 ++++---- .../store/actions/search-multiple.actions.ts | 17 ++++ .../src/app/instance/store/effects/index.ts | 2 + .../store/effects/search-multiple.effects.ts | 39 +++++++++ .../store/reducers/search-multiple.reducer.ts | 69 ++++++++++++++++ .../selectors/search-multiple.selector.ts | 73 +++++++++++++++++ 17 files changed, 311 insertions(+), 151 deletions(-) create mode 100644 client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.ts create mode 100644 client/src/app/instance/store/effects/search-multiple.effects.ts create mode 100644 client/src/app/instance/store/reducers/search-multiple.reducer.ts create mode 100644 client/src/app/instance/store/selectors/search-multiple.selector.ts diff --git a/client/src/app/instance/instance-routing.module.ts b/client/src/app/instance/instance-routing.module.ts index 03c0e21f..53ae1296 100644 --- a/client/src/app/instance/instance-routing.module.ts +++ b/client/src/app/instance/instance-routing.module.ts @@ -18,6 +18,7 @@ const routes: Routes = [ { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomeModule) }, { path: 'search', loadChildren: () => import('./search/search.module').then(m => m.SearchModule) }, + { path: 'search-multiple', loadChildren: () => import('./search-multiple/search-multiple.module').then(m => m.SearchMultipleModule) }, { path: 'documentation', loadChildren: () => import('./documentation/documentation.module').then(m => m.DocumentationModule) } ] } diff --git a/client/src/app/instance/instance.reducer.ts b/client/src/app/instance/instance.reducer.ts index 76e651be..d14c08ae 100644 --- a/client/src/app/instance/instance.reducer.ts +++ b/client/src/app/instance/instance.reducer.ts @@ -11,12 +11,14 @@ import { combineReducers, createFeatureSelector } from '@ngrx/store'; import { RouterReducerState } from 'src/app/custom-route-serializer'; import * as search from './store/reducers/search.reducer'; +import * as searchMultiple from './store/reducers/search-multiple.reducer'; import * as samp from './store/reducers/samp.reducer'; import * as coneSearch from './store/reducers/cone-search.reducer'; import * as detail from './store/reducers/detail.reducer'; export interface State { search: search.State, + searchMultiple: searchMultiple.State, samp: samp.State, coneSearch: coneSearch.State detail: detail.State @@ -24,6 +26,7 @@ export interface State { const reducers = { search: search.searchReducer, + searchMultiple: searchMultiple.searchMultipleReducer, samp: samp.sampReducer, coneSearch: coneSearch.coneSearchReducer, detail: detail.detailReducer diff --git a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.html b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.html index 0dc2981b..4e9fec69 100644 --- a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.html +++ b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.html @@ -6,18 +6,11 @@ </div> <div class="progress-navigation"> <div class="progress progress-with-circle"> - <div class="progress-bar" role="progressbar" aria-valuenow="1" aria-valuemin="1" aria-valuemax="4" - [ngClass]="getStepClass()"></div> + <div class="progress-bar" role="progressbar" aria-valuenow="1" aria-valuemin="1" aria-valuemax="4" [ngClass]="getStepClass()"></div> </div> <ul class="nav nav-pills"> <li class="nav-item checked" [ngClass]="{'active': currentStep === 'position'}"> - <a *ngIf="!noSelectedDatasets" class="nav-link" routerLink="/search-multiple/position" [queryParams]="queryParams" data-toggle="tab"> - <div class="icon-circle"> - <span class="fas fa-drafting-compass"></span> - </div> - Position - </a> - <a *ngIf="noSelectedDatasets" class="nav-link disabled" data-toggle="tab"> + <a class="nav-link" routerLink="/instance/{{ instance.name }}/search-multiple/position" [queryParams]="queryParams" data-toggle="tab"> <div class="icon-circle"> <span class="fas fa-drafting-compass"></span> </div> @@ -26,13 +19,13 @@ </li> <li class="nav-item" [ngClass]="{'active': currentStep === 'datasets', 'checked': datasetsStepChecked}"> - <a *ngIf="isValidConeSearch" class="nav-link" routerLink="/search-multiple/datasets" [queryParams]="queryParams" data-toggle="tab"> + <a *ngIf="coneSearch" class="nav-link" routerLink="/instance/{{ instance.name }}/search-multiple/datasets" [queryParams]="queryParams" data-toggle="tab"> <div class="icon-circle"> <span class="fas fa-book"></span> </div> Datasets </a> - <a *ngIf="!isValidConeSearch" class="nav-link disabled" data-toggle="tab"> + <a *ngIf="!coneSearch" class="nav-link disabled" data-toggle="tab"> <div class="icon-circle"> <span class="fas fa-book"></span> </div> @@ -41,13 +34,13 @@ </li> <li class="nav-item" [ngClass]="{'active': currentStep === 'result', 'checked': resultStepChecked}"> - <a *ngIf="isValidConeSearch && !noSelectedDatasets" class="nav-link" routerLink="/search-multiple/result" [queryParams]="queryParams" data-toggle="tab"> + <a *ngIf="coneSearch && selectedDatasets.length > 0" class="nav-link" routerLink="/instance/{{ instance.name }}/search-multiple/result" [queryParams]="queryParams" data-toggle="tab"> <div class="icon-circle"> <span class="fas fa-table"></span> </div> Result </a> - <a *ngIf="!isValidConeSearch || noSelectedDatasets" class="nav-link disabled" data-toggle="tab"> + <a *ngIf="!coneSearch || selectedDatasets.length < 1" class="nav-link disabled" data-toggle="tab"> <div class="icon-circle"> <span class="fas fa-table"></span> </div> diff --git a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts index 6060716b..d3c3d510 100644 --- a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts +++ b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts @@ -9,7 +9,8 @@ import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; -import { SearchMultipleQueryParams } from '../store/model'; +import { Instance } from 'src/app/metamodel/models'; +import { ConeSearch, SearchMultipleQueryParams } from 'src/app/instance/store/models'; @Component({ selector: 'app-progress-bar-multiple', @@ -22,12 +23,13 @@ import { SearchMultipleQueryParams } from '../store/model'; * @classdesc Search multiple progress bar component. */ export class ProgressBarMultipleComponent { + @Input() instance: Instance; @Input() currentStep: string; @Input() positionStepChecked: boolean; @Input() datasetsStepChecked: boolean; @Input() resultStepChecked: boolean; - @Input() isValidConeSearch: boolean; - @Input() noSelectedDatasets: boolean; + @Input() coneSearch: ConeSearch; + @Input() selectedDatasets: string[]; @Input() queryParams: SearchMultipleQueryParams; /** diff --git a/client/src/app/instance/search-multiple/components/summary-multiple.component.html b/client/src/app/instance/search-multiple/components/summary-multiple.component.html index b59975fc..3d604965 100644 --- a/client/src/app/instance/search-multiple/components/summary-multiple.component.html +++ b/client/src/app/instance/search-multiple/components/summary-multiple.component.html @@ -5,7 +5,7 @@ <p class="text-center font-italic"> Position </p> - <span *ngIf="isValidConeSearch" class="pl-5"> + <span *ngIf="coneSearch" class="pl-5"> Cone search: <ul class="ml-3 pl-5 list-unstyled"> <li>RA = {{ coneSearch.ra }}°</li> @@ -13,7 +13,7 @@ <li>radius = {{ coneSearch.radius }} arcsecond</li> </ul> </span> - <p *ngIf="!isValidConeSearch" class="pl-5 text-danger font-weight-bold"> + <p *ngIf="!coneSearch" class="pl-5 text-danger font-weight-bold"> Not valid position! </p> <hr> @@ -22,15 +22,11 @@ <p class="text-center font-italic"> Datasets </p> - <span *ngIf="datasetSearchMetaIsLoading" class="row justify-content-center mt-5"> - <span class="fas fa-circle-notch fa-spin fa-3x"></span> - <span class="sr-only">Loading...</span> - </span> - <div *ngIf="datasetSearchMetaIsLoaded"> - <p *ngIf="noSelectedDatasets" class="pl-5 text-danger font-weight-bold"> + <div> + <p *ngIf="selectedDatasets.length < 1" class="pl-5 text-danger font-weight-bold"> At least 1 dataset required! </p> - <div *ngIf="!noSelectedDatasets"> + <div *ngIf="selectedDatasets.length > 0"> <!-- Accordion Dataset families --> <accordion [isAnimated]="true"> <accordion-group *ngFor="let datasetFamily of getDatasetFamilyList()" #ag panelClass="abstract-accordion" [isOpen]="accordionFamilyIsOpen" class="pl-5"> diff --git a/client/src/app/instance/search-multiple/components/summary-multiple.component.ts b/client/src/app/instance/search-multiple/components/summary-multiple.component.ts index fabeefdf..790fcd5c 100644 --- a/client/src/app/instance/search-multiple/components/summary-multiple.component.ts +++ b/client/src/app/instance/search-multiple/components/summary-multiple.component.ts @@ -9,10 +9,8 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; -import { SearchMultipleQueryParams } from '../store/model'; -import { Dataset, Family } from '../../metamodel/model'; -import { ConeSearch } from '../../shared/cone-search/store/model'; -import { sortByDisplay } from '../../shared/utils'; +import { SearchMultipleQueryParams, ConeSearch } from 'src/app/instance/store/models'; +import { Dataset, DatasetFamily } from 'src/app/metamodel/models'; @Component({ selector: 'app-summary-multiple', @@ -26,15 +24,11 @@ import { sortByDisplay } from '../../shared/utils'; */ export class SummaryMultipleComponent { @Input() currentStep: string; - @Input() isValidConeSearch: boolean; @Input() coneSearch: ConeSearch; - @Input() datasetSearchMetaIsLoading: boolean; - @Input() datasetSearchMetaIsLoaded: boolean; - @Input() datasetFamilyList: Family[]; - @Input() datasetList: Dataset[]; @Input() selectedDatasets: string[]; - @Input() noSelectedDatasets: boolean; @Input() queryParams: SearchMultipleQueryParams; + @Input() datasetFamilyList: DatasetFamily[]; + @Input() datasetList: Dataset[]; accordionFamilyIsOpen = true; @@ -43,7 +37,7 @@ export class SummaryMultipleComponent { * * @return Family[] */ - getDatasetFamilyList(): Family[] { + getDatasetFamilyList(): DatasetFamily[] { const familiesId: number[] = []; this.datasetList.forEach(d => { if (!familiesId.includes(d.id_dataset_family)) { @@ -52,7 +46,7 @@ export class SummaryMultipleComponent { }); return this.datasetFamilyList .filter(f => familiesId.includes(f.id)) - .sort(sortByDisplay); + //.sort(sortByDisplay); } /** diff --git a/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.ts b/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.ts new file mode 100644 index 00000000..f83b809a --- /dev/null +++ b/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.ts @@ -0,0 +1,46 @@ +import { Directive } from '@angular/core'; + +import { Store } from '@ngrx/store'; +import { Observable } from 'rxjs'; + +import { Dataset, DatasetFamily } from 'src/app/metamodel/models'; +import { ConeSearch, SearchMultipleQueryParams } from '../../store/models'; +import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; +import * as datasetFamilySelector from 'src/app/metamodel/selectors/dataset-family.selector'; +import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; +import * as searchMultipleSelector from 'src/app/instance/store/selectors/search-multiple.selector'; +import * as coneSearchSelector from 'src/app/instance/store/selectors/cone-search.selector'; + +@Directive() +export abstract class AbstractSearchMultipleComponent { + public instanceSelected: Observable<string>; + public datasetFamilyListIsLoading: Observable<boolean>; + public datasetFamilyListIsLoaded: Observable<boolean>; + public datasetFamilyList: Observable<DatasetFamily[]>; + public datasetListIsLoading: Observable<boolean>; + public datasetListIsLoaded: Observable<boolean>; + public datasetList: Observable<Dataset[]>; + public pristine: Observable<boolean>; + public currentStep: Observable<string>; + public selectedDatasets: Observable<string[]>; + public coneSearch: Observable<ConeSearch>; + public queryParams: Observable<SearchMultipleQueryParams>; + + constructor(protected store: Store<{ }>) { + this.instanceSelected = this.store.select(instanceSelector.selectInstanceNameByRoute); + this.datasetFamilyListIsLoading = store.select(datasetFamilySelector.selectDatasetFamilyListIsLoading); + this.datasetFamilyListIsLoaded = store.select(datasetFamilySelector.selectDatasetFamilyListIsLoaded); + this.datasetFamilyList = store.select(datasetFamilySelector.selectAllDatasetFamilies); + this.datasetListIsLoading = this.store.select(datasetSelector.selectDatasetListIsLoading); + this.datasetListIsLoaded = this.store.select(datasetSelector.selectDatasetListIsLoaded); + this.datasetList = this.store.select(datasetSelector.selectAllDatasets); + this.pristine = this.store.select(searchMultipleSelector.selectPristine); + this.currentStep = this.store.select(searchMultipleSelector.selectCurrentStep) + this.selectedDatasets = this.store.select(searchMultipleSelector.selectSelectedDatasets); + this.coneSearch = this.store.select(coneSearchSelector.selectConeSearch); + this.queryParams = this.store.select(searchMultipleSelector.selectQueryParams); + } + + ngOnInit() { + } +} \ No newline at end of file diff --git a/client/src/app/instance/search-multiple/containers/position.component.html b/client/src/app/instance/search-multiple/containers/position.component.html index b9124abb..e7c2138b 100644 --- a/client/src/app/instance/search-multiple/containers/position.component.html +++ b/client/src/app/instance/search-multiple/containers/position.component.html @@ -1,42 +1,34 @@ -<div class="row mt-4"> +<app-spinner *ngIf="(datasetFamilyListIsLoading | async) || (datasetListIsLoading | async)"> +</app-spinner> + +<div *ngIf="(datasetFamilyListIsLoaded | async) && (datasetListIsLoaded | async)" class="row mt-4"> <div class="col-12 col-md-8 col-lg-9"> <div class="border rounded my-2"> <p class="border-bottom bg-light text-primary mb-0 py-4 pl-4">Cone Search</p> <div class="p-4"> - <app-cone-search></app-cone-search> + <!-- <app-cone-search></app-cone-search> <div class=" pt-3 text-center"> <button class="btn btn-outline-secondary" (click)="resetConeSearch()">Reset cone search</button> - </div> + </div> --> </div> </div> </div> <div class="col-12 col-md-4 col-lg-3 pt-2"> <app-summary-multiple [currentStep]="currentStep | async" - [isValidConeSearch]="isValidConeSearch | async" [coneSearch]="coneSearch | async" - [datasetSearchMetaIsLoading]="datasetSearchMetaIsLoading | async" - [datasetSearchMetaIsLoaded]="datasetSearchMetaIsLoaded | async" - [datasetFamilyList]="datasetFamilyList | async" - [datasetList]="datasetList | async" [selectedDatasets]="selectedDatasets | async" - [noSelectedDatasets]="noSelectedDatasets | async" - [queryParams]="queryParams | async"> + [queryParams]="queryParams | async" + [datasetFamilyList]="datasetFamilyList | async" + [datasetList]="datasetList | async"> </app-summary-multiple> </div> </div> -<div class="row mt-5 justify-content-end"> +<div *ngIf="coneSearch | async" class="row mt-5 justify-content-end"> <div class="col col-auto"> - <button *ngIf="!(isValidConeSearch | async)" class="btn btn-outline-primary disabled not-allowed" title="Not valid position!"> - Next <span class="fas fa-arrow-right"></span> - </button> - <a *ngIf="isValidConeSearch | async" - routerLink="/search-multiple/datasets" - [queryParams]="queryParams | async" - (click)="checkStep()" - class="btn btn-outline-primary"> - Next <span class="fas fa-arrow-right"></span> + <a routerLink="/instance/{{ instanceSelected | async}}/search-multiple/datasets}" [queryParams]="queryParams | async" + class="btn btn-outline-primary">Datasets <span class="fas fa-arrow-right"></span> </a> </div> </div> diff --git a/client/src/app/instance/search-multiple/containers/position.component.ts b/client/src/app/instance/search-multiple/containers/position.component.ts index f5541c63..a7aa89f9 100644 --- a/client/src/app/instance/search-multiple/containers/position.component.ts +++ b/client/src/app/instance/search-multiple/containers/position.component.ts @@ -7,90 +7,26 @@ * file that was distributed with this source code. */ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs'; -import * as fromSearchMultiple from '../store/search-multiple.reducer'; -import * as searchMultipleActions from '../store/search-multiple.action'; -import * as searchMultipleSelector from '../store/search-multiple.selector'; -import { SearchMultipleQueryParams } from '../store/model'; -import * as datasetActions from '../../metamodel/action/dataset.action'; -import * as fromMetamodel from '../../metamodel/reducers'; -import * as metamodelSelector from '../../metamodel/selectors'; -import { Dataset, Family } from '../../metamodel/model'; -import * as coneSearchActions from '../../shared/cone-search/store/cone-search.action'; -import * as coneSearchSelector from '../../shared/cone-search/store/cone-search.selector'; -import { ConeSearch } from '../../shared/cone-search/store/model'; -import { ScrollTopService } from '../../shared/service/sroll-top.service'; - -/** - * Interface for store state. - * - * @interface StoreState - */ -interface StoreState { - searchMultiple: fromSearchMultiple.State; - metamodel: fromMetamodel.State; -} +import { AbstractSearchMultipleComponent } from './abstract-search-multiple.component'; +import * as searchMultipleActions from '../../store/actions/search-multiple.actions'; @Component({ selector: 'app-position', templateUrl: 'position.component.html', styleUrls: ['position.component.scss'] }) -/** - * @class - * @classdesc Search multiple position container. - * - * @implements OnInit - */ -export class PositionComponent implements OnInit { - public datasetSearchMetaIsLoading: Observable<boolean>; - public datasetSearchMetaIsLoaded: Observable<boolean>; - public currentStep: Observable<string>; - public isValidConeSearch: Observable<boolean>; - public coneSearch: Observable<ConeSearch>; - public datasetFamilyList: Observable<Family[]>; - public datasetList: Observable<Dataset[]>; - public selectedDatasets: Observable<string[]>; - public noSelectedDatasets: Observable<boolean>; - public queryParams: Observable<SearchMultipleQueryParams>; +export class PositionComponent extends AbstractSearchMultipleComponent { - constructor(private store: Store<StoreState>, private scrollTopService: ScrollTopService) { - this.datasetSearchMetaIsLoading = store.select(metamodelSelector.getDatasetSearchMetaIsLoading); - this.datasetSearchMetaIsLoaded = store.select(metamodelSelector.getDatasetSearchMetaIsLoaded); - this.currentStep = store.select(searchMultipleSelector.getCurrentStep); - this.isValidConeSearch = this.store.select(coneSearchSelector.getIsValidConeSearch); - this.coneSearch = this.store.select(coneSearchSelector.getConeSearch); - this.datasetFamilyList = store.select(metamodelSelector.getDatasetFamilyList); - this.datasetList = store.select(metamodelSelector.getDatasetWithConeSearchList); - this.selectedDatasets = store.select(searchMultipleSelector.getSelectedDatasets); - this.noSelectedDatasets = store.select(searchMultipleSelector.getNoSelectedDatasets); - this.queryParams = this.store.select(searchMultipleSelector.getQueryParams); + constructor(protected store: Store<{ }>) { + super(store); + Promise.resolve(null).then(() => this.store.dispatch(searchMultipleActions.changeStep({ step: 'position' }))); } ngOnInit() { - // Create a micro task that is processed after the current synchronous code - // This micro task prevent the expression has changed after view init error - Promise.resolve(null).then(() => this.store.dispatch(new searchMultipleActions.InitSearchByUrlAction())); - Promise.resolve(null).then(() => this.store.dispatch(new searchMultipleActions.ChangeStepAction('position'))); - this.store.dispatch(new datasetActions.LoadDatasetSearchMetaAction()); - this.scrollTopService.setScrollTop(); - } - - /** - * Dispatches action to check position step. - */ - checkStep(): void { - this.store.dispatch(new searchMultipleActions.PositionCheckedAction()); - } - - /** - * Dispatches action to reset cone search. - */ - resetConeSearch(): void { - this.store.dispatch(new coneSearchActions.DeleteConeSearchAction()); + } } diff --git a/client/src/app/instance/search-multiple/search-multiple-routing.module.ts b/client/src/app/instance/search-multiple/search-multiple-routing.module.ts index 3f84f0f1..ca77e734 100644 --- a/client/src/app/instance/search-multiple/search-multiple-routing.module.ts +++ b/client/src/app/instance/search-multiple/search-multiple-routing.module.ts @@ -17,7 +17,7 @@ const routes: Routes = [ { path: '', component: SearchMultipleComponent, children: [ { path: '', redirectTo: 'position', pathMatch: 'full' }, - { path: 'dataset', component: PositionComponent } + { path: 'position', component: PositionComponent } ] } ]; diff --git a/client/src/app/instance/search-multiple/search-multiple.component.html b/client/src/app/instance/search-multiple/search-multiple.component.html index c3301e3f..7f7342be 100644 --- a/client/src/app/instance/search-multiple/search-multiple.component.html +++ b/client/src/app/instance/search-multiple/search-multiple.component.html @@ -1,11 +1,12 @@ <div class="mx-1 mx-sm-5 px-1 px-sm-5"> <app-progress-bar-multiple + [instance]="instance | async" [currentStep]="currentStep | async" [positionStepChecked]="positionStepChecked | async" [datasetsStepChecked]="datasetsStepChecked | async" [resultStepChecked]="resultStepChecked | async" - [isValidConeSearch]="isValidConeSearch | async" - [noSelectedDatasets]="noSelectedDatasets | async" + [coneSearch]="coneSearch | async" + [selectedDatasets]="selectedDatasets | async" [queryParams]="queryParams | async"> </app-progress-bar-multiple> <router-outlet></router-outlet> diff --git a/client/src/app/instance/search-multiple/search-multiple.component.ts b/client/src/app/instance/search-multiple/search-multiple.component.ts index e5d5e1b9..b0d2b7b8 100644 --- a/client/src/app/instance/search-multiple/search-multiple.component.ts +++ b/client/src/app/instance/search-multiple/search-multiple.component.ts @@ -12,14 +12,11 @@ import { Component, } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; -import { SearchMultipleQueryParams } from '../store/models'; +import { ConeSearch, SearchMultipleQueryParams } from '../store/models'; import { Instance } from 'src/app/metamodel/models'; - -import * as searchMultipleReducer from '../store/search-multiple.reducer'; -import * as searchMultipleSelector from '../store/search-multiple.selector'; -import * as searchActions from '../../search/store/search.action'; -import * as coneSearchSelector from '../../shared/cone-search/store/cone-search.selector'; -import * as coneSearchActions from '../../shared/cone-search/store/cone-search.action'; +import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; +import * as searchMultipleSelector from '../store/selectors/search-multiple.selector'; +import * as coneSearchSelector from '../store/selectors/cone-search.selector'; @Component({ selector: 'app-search-multiple', @@ -35,19 +32,18 @@ export class SearchMultipleComponent { public positionStepChecked: Observable<boolean>; public datasetsStepChecked: Observable<boolean>; public resultStepChecked: Observable<boolean>; - public isValidConeSearch: Observable<boolean>; - public noSelectedDatasets: Observable<boolean>; + public coneSearch: Observable<ConeSearch>; + public selectedDatasets: Observable<string[]>; public queryParams: Observable<SearchMultipleQueryParams>; - constructor(private store: Store<searchMultipleReducer.State>) { - this.currentStep = store.select(searchMultipleSelector.getCurrentStep); - this.positionStepChecked = store.select(searchMultipleSelector.getPositionStepChecked); - this.datasetsStepChecked = store.select(searchMultipleSelector.getDatasetsStepChecked); - this.resultStepChecked = store.select(searchMultipleSelector.getResultStepChecked); - this.isValidConeSearch = store.select(coneSearchSelector.getIsValidConeSearch); - this.noSelectedDatasets = store.select(searchMultipleSelector.getNoSelectedDatasets); - this.queryParams = store.select(searchMultipleSelector.getQueryParams); - this.store.dispatch(new searchActions.ResetSearchAction()); - this.store.dispatch(new coneSearchActions.DeleteConeSearchAction()); + constructor(private store: Store<{ }>) { + this.instance = this.store.select(instanceSelector.selectInstanceByRouteName); + this.currentStep = this.store.select(searchMultipleSelector.selectCurrentStep); + this.positionStepChecked = this.store.select(searchMultipleSelector.selectPositionStepChecked); + this.datasetsStepChecked = this.store.select(searchMultipleSelector.selectDatasetsStepChecked); + this.resultStepChecked = this.store.select(searchMultipleSelector.selectResultStepChecked); + this.coneSearch = this.store.select(coneSearchSelector.selectConeSearch); + this.selectedDatasets = this.store.select(searchMultipleSelector.selectSelectedDatasets); + this.queryParams = this.store.select(searchMultipleSelector.selectQueryParams); } } diff --git a/client/src/app/instance/store/actions/search-multiple.actions.ts b/client/src/app/instance/store/actions/search-multiple.actions.ts index b28b0ac2..8559feb4 100644 --- a/client/src/app/instance/store/actions/search-multiple.actions.ts +++ b/client/src/app/instance/store/actions/search-multiple.actions.ts @@ -9,3 +9,20 @@ import { createAction, props } from '@ngrx/store'; +export const initSearch = createAction('[Search Multiple] Init Search'); +export const restartSearch = createAction('[Search Multiple] Restart Search'); +export const resetSearch = createAction('[Search Multiple] Reset Search'); +export const destroyResults = createAction('[Search Multiple] Destroy Results'); +export const loadDefaultFormParameters = createAction('[Search Multiple] Load Default Form Parameters'); +export const markAsDirty = createAction('[Search Multiple] Mark As Dirty'); +export const changeStep = createAction('[Search Multiple] Change Step', props<{ step: string }>()); +export const checkPosition = createAction('[Search Multiple] Check Position'); +export const checkDatasets = createAction('[Search Multiple] Check Datasets'); +export const checkResult = createAction('[Search Multiple] Check Result'); +export const updateSelectedDatasets = createAction('[Search Multiple] Update Selected Datasets', props<{ selectedDatasets: string[] }>()); +export const retrieveDataLength = createAction('[Search Multiple] Retrieve Data Length'); +export const retrieveDataLengthSuccess = createAction('[Search Multiple] Retrieve Data Length Success', props<{ length: number }>()); +export const retrieveDataLengthFail = createAction('[Search Multiple] Retrieve Data Length Fail'); +export const retrieveData = createAction('[Search Multiple] Retrieve Data'); +export const retrieveDataSuccess = createAction('[Search Multiple] Retrieve Data Success', props<{ data: any[] }>()); +export const retrieveDataFail = createAction('[Search Multiple] Retrieve Data Fail'); diff --git a/client/src/app/instance/store/effects/index.ts b/client/src/app/instance/store/effects/index.ts index 132bb177..582dd511 100644 --- a/client/src/app/instance/store/effects/index.ts +++ b/client/src/app/instance/store/effects/index.ts @@ -1,11 +1,13 @@ import { SampEffects } from './samp.effects'; import { SearchEffects } from './search.effects'; +import { SearchMultipleEffects } from './search-multiple.effects'; import { ConeSearchEffects } from './cone-search.effects'; import { DetailEffects } from './detail.effects'; export const instanceEffects = [ SampEffects, SearchEffects, + SearchMultipleEffects, ConeSearchEffects, DetailEffects ]; diff --git a/client/src/app/instance/store/effects/search-multiple.effects.ts b/client/src/app/instance/store/effects/search-multiple.effects.ts new file mode 100644 index 00000000..e6c26c9c --- /dev/null +++ b/client/src/app/instance/store/effects/search-multiple.effects.ts @@ -0,0 +1,39 @@ +/** + * This file is part of Anis Client. + * + * @copyright Laboratoire d'Astrophysique de Marseille / CNRS + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { Injectable } from '@angular/core'; + +import { Actions, createEffect, ofType, concatLatestFrom } from '@ngrx/effects'; +import { Store, Action } from '@ngrx/store'; +import { of } from 'rxjs'; +import { map, tap, mergeMap, catchError } from 'rxjs/operators'; +import { ToastrService } from 'ngx-toastr'; + +import { ConeSearch, criterionToString, stringToCriterion } from '../models'; +import { SearchService } from '../services/search.service'; +import * as searchActions from '../actions/search.actions'; +import * as attributeActions from 'src/app/metamodel/actions/attribute.actions'; +import * as attributeSelector from 'src/app/metamodel/selectors/attribute.selector'; +import * as criteriaFamilyActions from 'src/app/metamodel/actions/criteria-family.actions'; +import * as outputFamilyActions from 'src/app/metamodel/actions/output-family.actions'; +import * as outputCategoryActions from 'src/app/metamodel/actions/output-category.actions'; +import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; +import * as searchSelector from '../selectors/search.selector'; +import * as coneSearchActions from '../actions/cone-search.actions'; +import * as coneSearchSelector from '../selectors/cone-search.selector'; + +@Injectable() +export class SearchMultipleEffects { + constructor( + private actions$: Actions, + private searchService: SearchService, + private store: Store<{ }>, + private toastr: ToastrService + ) {} +} diff --git a/client/src/app/instance/store/reducers/search-multiple.reducer.ts b/client/src/app/instance/store/reducers/search-multiple.reducer.ts new file mode 100644 index 00000000..25dcaf67 --- /dev/null +++ b/client/src/app/instance/store/reducers/search-multiple.reducer.ts @@ -0,0 +1,69 @@ +/** + * This file is part of Anis Client. + * + * @copyright Laboratoire d'Astrophysique de Marseille / CNRS + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { createReducer, on } from '@ngrx/store'; + +import * as searchMultipleActions from '../actions/search-multiple.actions'; + +export interface State { + pristine: boolean; + currentStep: string; + positionStepChecked: boolean; + datasetsStepChecked: boolean; + resultStepChecked: boolean; + selectedDatasets: string[]; +} + +export const initialState: State = { + pristine: true, + currentStep: null, + positionStepChecked: false, + datasetsStepChecked: false, + resultStepChecked: false, + selectedDatasets: [] +}; + +export const searchMultipleReducer = createReducer( + initialState, + on(searchMultipleActions.restartSearch, () => ({ + ...initialState, + currentStep: 'position' + })), + on(searchMultipleActions.changeStep, (state, { step }) => ({ + ...state, + currentStep: step + })), + on(searchMultipleActions.markAsDirty, state => ({ + ...state, + pristine: false + })), + on(searchMultipleActions.checkPosition, state => ({ + ...state, + positionStepChecked: true + })), + on(searchMultipleActions.checkDatasets, state => ({ + ...state, + datasetsStepChecked: true + })), + on(searchMultipleActions.checkResult, state => ({ + ...state, + resultStepChecked: true + })), + on(searchMultipleActions.updateSelectedDatasets, (state, { selectedDatasets }) => ({ + ...state, + selectedDatasets + })) +); + +export const selectPristine = (state: State) => state.pristine; +export const selectCurrentStep = (state: State) => state.currentStep; +export const selectPositionStepChecked = (state: State) => state.positionStepChecked; +export const selectDatasetsStepChecked = (state: State) => state.datasetsStepChecked; +export const selectResultStepChecked = (state: State) => state.resultStepChecked; +export const selectSelectedDatasets = (state: State) => state.selectedDatasets; diff --git a/client/src/app/instance/store/selectors/search-multiple.selector.ts b/client/src/app/instance/store/selectors/search-multiple.selector.ts new file mode 100644 index 00000000..9e88a69b --- /dev/null +++ b/client/src/app/instance/store/selectors/search-multiple.selector.ts @@ -0,0 +1,73 @@ +/** + * This file is part of Anis Client. + * + * @copyright Laboratoire d'Astrophysique de Marseille / CNRS + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { createSelector } from '@ngrx/store'; + +import { SearchMultipleQueryParams, ConeSearch } from '../models'; +import * as reducer from '../../instance.reducer'; +import * as fromSearchMultiple from '../reducers/search-multiple.reducer'; +import * as coneSearchSelector from './cone-search.selector'; + +export const selectSearchMultipleState = createSelector( + reducer.getInstanceState, + (state: reducer.State) => state.searchMultiple +); + +export const selectPristine = createSelector( + selectSearchMultipleState, + fromSearchMultiple.selectPristine +); + +export const selectCurrentStep = createSelector( + selectSearchMultipleState, + fromSearchMultiple.selectCurrentStep +); + +export const selectPositionStepChecked = createSelector( + selectSearchMultipleState, + fromSearchMultiple.selectPositionStepChecked +); + +export const selectDatasetsStepChecked = createSelector( + selectSearchMultipleState, + fromSearchMultiple.selectDatasetsStepChecked +); + +export const selectResultStepChecked = createSelector( + selectSearchMultipleState, + fromSearchMultiple.selectResultStepChecked +); + +export const selectSelectedDatasets = createSelector( + selectSearchMultipleState, + fromSearchMultiple.selectSelectedDatasets +); + +export const selectQueryParams = createSelector( + coneSearchSelector.selectConeSearch, + selectSelectedDatasets, + ( + coneSearch: ConeSearch, + selectedDatasets: string[]) => { + let queryParams: SearchMultipleQueryParams = { }; + if (coneSearch) { + queryParams = { + ...queryParams, + cs: coneSearch.ra + ':' + coneSearch.dec + ':' + coneSearch.radius + }; + } + if (selectedDatasets.length > 0) { + queryParams = { + ...queryParams, + d: selectedDatasets.join(';') + }; + } + return queryParams; + } +); -- GitLab