diff --git a/src/app/search-multiple/components/dataset-list.component.html b/src/app/search-multiple/components/dataset-list.component.html index 8a99e5fe476b9e25ce919955b56067e92ded4795..6feadc596866901a175ffd8f72a0328813baa173 100644 --- a/src/app/search-multiple/components/dataset-list.component.html +++ b/src/app/search-multiple/components/dataset-list.component.html @@ -1,12 +1,12 @@ <div class="row"> - <div *ngFor="let project of getProjectSortedByName()" class="col-12 col-md-4 my-3 text-center"> + <div *ngFor="let project of getProjectSortedByName()" class="col-12 col-lg-6 col-xl-4 my-3 text-center"> <app-datasets-by-project [project]="project" [datasetList]="getDatasetsByProject(project.name)" [selectedDatasets]="selectedDatasets" [isAllSelected]="getIsAllSelected(project.name)" [isAllUnselected]="getIsAllUnselected(project.name)" - (updateDatasetList)="updateDatasetList.emit($event)"> + (updateSelectedDatasets)="updateSelectedDatasets.emit($event)"> </app-datasets-by-project> </div> </div> \ No newline at end of file diff --git a/src/app/search-multiple/components/dataset-list.component.ts b/src/app/search-multiple/components/dataset-list.component.ts index 88042cd03e65c37ae2ea9fea7c12d4f4a3abcd1b..65df95171297779e03a4cfa37388f970163849b2 100644 --- a/src/app/search-multiple/components/dataset-list.component.ts +++ b/src/app/search-multiple/components/dataset-list.component.ts @@ -1,7 +1,5 @@ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core'; -// import { Family, Category, Attribute } from '../../../metamodel/model'; -// import { sortByDisplay } from '../../../shared/utils'; import { Dataset, Project } from "../../metamodel/model"; @Component({ @@ -13,18 +11,11 @@ export class DatasetListComponent { @Input() projectList: Project[]; @Input() datasetList: Dataset[]; @Input() selectedDatasets: string[]; - @Output() updateDatasetList: EventEmitter<string[]> = new EventEmitter(); + @Output() updateSelectedDatasets: EventEmitter<string[]> = new EventEmitter(); getProjectSortedByName(): Project[] { - // this.projectList.sort((a, b) => { - // // console.log(a.name, ' | ', b.name, ' | ', a.name.localeCompare(b.name)); - // // return a.name.localeCompare(b.name); - // return -1 - // }); - let plist: Project[] = [...this.projectList]; - console.log(plist.sort((a, b) => a.name.localeCompare(b.name))); - return this.projectList; + return [...this.projectList].sort((a, b) => a.name.localeCompare(b.name)); } getDatasetsByProject(projectName: string): Dataset[] { @@ -42,13 +33,4 @@ export class DatasetListComponent { const filteredSelectedDatasets = this.selectedDatasets.filter(name => datasetListName.indexOf(name) > -1); return filteredSelectedDatasets.length === 0; } - - // emitChange(clonedOutputList: number[]): void { - // this.change.emit( - // this.datasetAttributeList - // .filter(a => clonedOutputList.indexOf(a.id) > -1) - // .sort((a, b) => a.output_display - b.output_display) - // .map(a => a.id) - // ); - // } } diff --git a/src/app/search-multiple/components/datasets-by-projet.component.ts b/src/app/search-multiple/components/datasets-by-projet.component.ts index 00546ce747e1b310eddb16e5912a520be42bfaf6..b620613154a8b27c539ca6623d566bdca5decabc 100644 --- a/src/app/search-multiple/components/datasets-by-projet.component.ts +++ b/src/app/search-multiple/components/datasets-by-projet.component.ts @@ -14,7 +14,7 @@ export class DatasetsByProjetComponent { @Input() selectedDatasets: string[]; @Input() isAllSelected: boolean; @Input() isAllUnselected: boolean; - @Output() updateDatasetList: EventEmitter<string[]> = new EventEmitter(); + @Output() updateSelectedDatasets: EventEmitter<string[]> = new EventEmitter(); getDatasetSortedByDisplay(): Dataset[] { return this.datasetList.sort(sortByDisplay); @@ -32,7 +32,7 @@ export class DatasetsByProjetComponent { } else { clonedSelectedDatasets.push(dname); } - this.updateDatasetList.emit(clonedSelectedDatasets); + this.updateSelectedDatasets.emit(clonedSelectedDatasets); } selectAll(): void { @@ -41,7 +41,7 @@ export class DatasetsByProjetComponent { datasetListName.filter(name => clonedSelectedDatasets.indexOf(name) === -1).forEach(name => { clonedSelectedDatasets.push(name); }); - this.updateDatasetList.emit(clonedSelectedDatasets); + this.updateSelectedDatasets.emit(clonedSelectedDatasets); } unselectAll(): void { @@ -51,6 +51,6 @@ export class DatasetsByProjetComponent { const index = clonedSelectedDatasets.indexOf(name); clonedSelectedDatasets.splice(index, 1); }); - this.updateDatasetList.emit(clonedSelectedDatasets); + this.updateSelectedDatasets.emit(clonedSelectedDatasets); } } diff --git a/src/app/search-multiple/components/summary-multiple.component.html b/src/app/search-multiple/components/summary-multiple.component.html index 05e82e8c03c5923db653998b62594dda6f296dff..9dc698a6f7c69819a0ddf4df205692245926e538 100644 --- a/src/app/search-multiple/components/summary-multiple.component.html +++ b/src/app/search-multiple/components/summary-multiple.component.html @@ -27,58 +27,37 @@ <span class="sr-only">Loading...</span> </span> <div *ngIf="datasetSearchMetaIsLoaded"> - <p *ngIf="!datasetList" class="pl-5 text-danger font-weight-bold"> + <p *ngIf="noSelectedDatasets" class="pl-5 text-danger font-weight-bold"> At least 1 dataset required! </p> - <div *ngIf="datasetList"> - <ul class="ml-3 pl-5 list-unstyled"> - <li *ngFor="let dataset of datasetList">{{ dataset.label }}</li> - </ul> - <!-- <!– Accordion families –>--> - <!-- <accordion [isAnimated]="true">--> - <!-- <accordion-group *ngFor="let family of outputFamilyList" #ag panelClass="abstract-accordion" [isOpen]="accordionFamilyIsOpen" class="pl-5">--> - <!-- <button class="btn btn-link btn-block clearfix pb-1 text-primary" accordion-heading>--> - <!-- <div class="pull-left float-left">--> - <!-- {{ family.label }}--> - <!-- --> - <!-- <span *ngIf="ag.isOpen">--> - <!-- <span class="fas fa-chevron-up"></span>--> - <!-- </span>--> - <!-- <span *ngIf="!ag.isOpen">--> - <!-- <span class="fas fa-chevron-down"></span>--> - <!-- </span>--> - <!-- </div>--> - <!-- </button>--> + <div *ngIf="!noSelectedDatasets"> + <!-- Accordion projects --> + <accordion [isAnimated]="true"> + <accordion-group *ngFor="let project of getProjectSortedByName()" #ag panelClass="abstract-accordion" [isOpen]="accordionProjectIsOpen" class="pl-5"> + <button class="btn btn-link btn-block clearfix pb-1 text-primary" accordion-heading> + <div class="pull-left float-left"> + {{ project.label }} + + <span *ngIf="ag.isOpen"> + <span class="fas fa-chevron-up"></span> + </span> + <span *ngIf="!ag.isOpen"> + <span class="fas fa-chevron-down"></span> + </span> + </div> + </button> - <!-- <!– Accordion categories –>--> - <!-- <accordion [isAnimated]="true">--> - <!-- <accordion-group *ngFor="let category of getCategoryByFamilySortedByDisplay(family.id)" #ag panelClass="abstract-accordion" [isOpen]="currentStep === 'output' || outputList.length < 10" class="pl-4">--> - <!-- <button class="btn btn-link btn-block clearfix pb-1" accordion-heading>--> - <!-- <div class="pull-left float-left text-primary">--> - <!-- {{ category.label }}--> - <!-- --> - <!-- <span *ngIf="ag.isOpen">--> - <!-- <span class="fas fa-chevron-up"></span>--> - <!-- </span>--> - <!-- <span *ngIf="!ag.isOpen">--> - <!-- <span class="fas fa-chevron-down"></span>--> - <!-- </span>--> - <!-- </div>--> - <!-- </button>--> - - <!-- <!– Output list –>--> - <!-- <ul *ngIf="getSelectedOutputByCategory(category.id).length > 0; else noOutputs" class="mb-0 pl-4 list-unstyled">--> - <!-- <li *ngFor="let output of getSelectedOutputByCategory(category.id)" class="pb-1">--> - <!-- {{ output.form_label }}--> - <!-- </li>--> - <!-- </ul>--> - <!-- <ng-template #noOutputs>--> - <!-- <p class="mb-1 pl-4">No selected output</p>--> - <!-- </ng-template>--> - <!-- </accordion-group>--> - <!-- </accordion>--> - <!-- </accordion-group>--> - <!-- </accordion>--> + <!-- Selected Datasets --> + <ul *ngIf="getSelectedDatasetsByProject(project.name).length > 0; else noDataset" class="mb-0 pl-4 list-unstyled"> + <li *ngFor="let dataset of getSelectedDatasetsByProject(project.name)" class="pb-1"> + {{ dataset.label }} + </li> + </ul> + <ng-template #noDataset> + <p class="mb-1 pl-4">No selected dataset</p> + </ng-template> + </accordion-group> + </accordion> </div> </div> </div> diff --git a/src/app/search-multiple/components/summary-multiple.component.ts b/src/app/search-multiple/components/summary-multiple.component.ts index 5629586d03b7ab7bb3bd2b637875c08eb15e87e9..f245bf1b6c9db948e3d10252787d6f7f0c0c4be3 100644 --- a/src/app/search-multiple/components/summary-multiple.component.ts +++ b/src/app/search-multiple/components/summary-multiple.component.ts @@ -1,6 +1,6 @@ -import {ChangeDetectionStrategy, Component, Input, ViewEncapsulation} from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; -import { Dataset } from '../../metamodel/model'; +import { Dataset, Project } from '../../metamodel/model'; import { ConeSearch } from "../../shared/cone-search/store/model"; import { SearchMultipleQueryParams } from "../store/model"; @@ -9,7 +9,6 @@ import { SearchMultipleQueryParams } from "../store/model"; templateUrl: 'summary-multiple.component.html', styleUrls: ['summary-multiple.component.css'], changeDetection: ChangeDetectionStrategy.OnPush, - // encapsulation: ViewEncapsulation.None }) export class SummaryMultipleComponent { @Input() currentStep: string; @@ -17,6 +16,21 @@ export class SummaryMultipleComponent { @Input() coneSearch: ConeSearch; @Input() datasetSearchMetaIsLoading: boolean; @Input() datasetSearchMetaIsLoaded: boolean; + @Input() projectList: Project[]; @Input() datasetList: Dataset[]; + @Input() selectedDatasets: string[]; + @Input() noSelectedDatasets: boolean; @Input() queryParams: SearchMultipleQueryParams; + + accordionProjectIsOpen = true; + + getProjectSortedByName(): Project[] { + return [...this.projectList].sort((a, b) => a.name.localeCompare(b.name)); + } + + getSelectedDatasetsByProject(projectName: string): Dataset[] { + return this.datasetList + .filter(d => d.project_name === projectName) + .filter(d => this.selectedDatasets.includes(d.name)); + } } diff --git a/src/app/search-multiple/containers/datasets.component.html b/src/app/search-multiple/containers/datasets.component.html index acf7b348d50f548fd19672a7e12938174055e7f3..1cdfd9c6527ff304a9967a36ef7ffb766260545b 100644 --- a/src/app/search-multiple/containers/datasets.component.html +++ b/src/app/search-multiple/containers/datasets.component.html @@ -1,15 +1,22 @@ <div class="row mt-4"> - <div *ngIf="datasetSearchMetaIsLoading | async" class="col-12 col-md-8 col-lg-9 text-center mt-5"> - <span class="fas fa-circle-notch fa-spin fa-3x"></span> - <span class="sr-only">Loading...</span> - </div> - <div *ngIf="datasetSearchMetaIsLoaded | async" class="col-12 col-md-8 col-lg-9"> - <app-dataset-list - [projectList]="projectList | async" - [datasetList]="datasetList | async" - [selectedDatasets]="selectedDatasets | async" - (updateDatasetList)="updateDatasetList($event)"> - </app-dataset-list> + <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">Datasets</p> + <div class="px-3"> + <div *ngIf="datasetSearchMetaIsLoading | async" class="text-center my-5"> + <span class="fas fa-circle-notch fa-spin fa-3x"></span> + <span class="sr-only">Loading...</span> + </div> +<!-- <div *ngIf="datasetSearchMetaIsLoaded | async">--> + <app-dataset-list *ngIf="datasetSearchMetaIsLoaded | async" + [projectList]="projectList | async" + [datasetList]="datasetList | async" + [selectedDatasets]="selectedDatasets | async" + (updateSelectedDatasets)="updateSelectedDatasets($event)"> + </app-dataset-list> +<!-- </div>--> + </div> + </div> </div> <div class="col-12 col-md-4 col-lg-3 pt-2"> <app-summary-multiple @@ -18,19 +25,36 @@ [coneSearch]="coneSearch | async" [datasetSearchMetaIsLoading]="datasetSearchMetaIsLoading | async" [datasetSearchMetaIsLoaded]="datasetSearchMetaIsLoaded | async" + [projectList]="projectList | async" [datasetList]="datasetList | async" + [selectedDatasets]="selectedDatasets | async" + [noSelectedDatasets]="noSelectedDatasets | async" [queryParams]="queryParams | async"> </app-summary-multiple> </div> </div> + <div class="row mt-5 justify-content-between"> <div class="col"> - <a routerLink="/search-multiple/position" [queryParams]="queryParams | async" class="btn btn-outline-secondary"> + <button *ngIf="noSelectedDatasets | async" class="btn btn-outline-secondary disabled not-allowed" title="At least one dataset required!"> + <span class="fas fa-arrow-left"></span> Previous + </button> + <a *ngIf="!(noSelectedDatasets | async)" + routerLink="/search-multiple/position" + [queryParams]="queryParams | async" + (click)="checkStep()" + class="btn btn-outline-secondary"> <span class="fas fa-arrow-left"></span> Previous </a> </div> <div class="col col-auto"> - <a routerLink="/search-multiple/result" [queryParams]="queryParams | async" + <button *ngIf="noSelectedDatasets | async" class="btn btn-outline-primary disabled not-allowed" title="At least one dataset required!"> + Next <span class="fas fa-arrow-right"></span> + </button> + <a *ngIf="!(noSelectedDatasets | async)" + routerLink="/search-multiple/result" + [queryParams]="queryParams | async" + (click)="checkStep()" class="btn btn-outline-primary"> Next <span class="fas fa-arrow-right"></span> </a> diff --git a/src/app/search-multiple/containers/datasets.component.ts b/src/app/search-multiple/containers/datasets.component.ts index a3c06d533570c9c674cde048a342a5820827532e..ac1b22ca66a6a10feb2628511a33770cd5b1889e 100644 --- a/src/app/search-multiple/containers/datasets.component.ts +++ b/src/app/search-multiple/containers/datasets.component.ts @@ -33,6 +33,7 @@ export class DatasetsComponent implements OnInit { public isValidConeSearch: Observable<boolean>; public coneSearch: Observable<ConeSearch>; public selectedDatasets: Observable<string[]>; + public noSelectedDatasets: Observable<boolean>; public queryParams: Observable<SearchMultipleQueryParams>; constructor(private store: Store<StoreState>, private scrollTopService: ScrollTopService) { @@ -43,8 +44,8 @@ export class DatasetsComponent implements OnInit { this.datasetList = store.select(metamodelSelector.getDatasetList); this.isValidConeSearch = this.store.select(coneSearchSelector.getIsValidConeSearch); this.selectedDatasets = this.store.select(searchMultipleSelector.getSelectedDatasets); + this.noSelectedDatasets = this.store.select(searchMultipleSelector.getNoSelectedDatasets); this.coneSearch = this.store.select(coneSearchSelector.getConeSearch); - this.queryParams = this.store.select(searchMultipleSelector.getQueryParams); } @@ -61,7 +62,7 @@ export class DatasetsComponent implements OnInit { this.store.dispatch(new searchMultipleActions.DatasetsCheckedAction()); } - updateDatasetList(datasetList: string[]) { - console.log(datasetList); + updateSelectedDatasets(selectedDatasets: string[]) { + this.store.dispatch(new searchMultipleActions.UpdateSelectedDatasetsAction(selectedDatasets)); } } diff --git a/src/app/search-multiple/containers/position.component.html b/src/app/search-multiple/containers/position.component.html index 851693c60f171e303e837b501a4a9190725e68a4..138b3efd16f29c7461149eefabd53f733596dfc7 100644 --- a/src/app/search-multiple/containers/position.component.html +++ b/src/app/search-multiple/containers/position.component.html @@ -1,6 +1,11 @@ <div class="row mt-4"> <div class="col-12 col-md-8 col-lg-9"> - <app-cone-search></app-cone-search> + <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> + </div> + </div> </div> <div class="col-12 col-md-4 col-lg-3 pt-2"> <app-summary-multiple @@ -9,11 +14,15 @@ [coneSearch]="coneSearch | async" [datasetSearchMetaIsLoading]="datasetSearchMetaIsLoading | async" [datasetSearchMetaIsLoaded]="datasetSearchMetaIsLoaded | async" + [projectList]="projectList | async" [datasetList]="datasetList | async" + [selectedDatasets]="selectedDatasets | async" + [noSelectedDatasets]="noSelectedDatasets | async" [queryParams]="queryParams | async"> </app-summary-multiple> </div> </div> + <div 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!"> diff --git a/src/app/search-multiple/containers/position.component.ts b/src/app/search-multiple/containers/position.component.ts index 67b9d6329d4c6ae1b07c567bfca98417898024cf..8f049529abfb9903fed890d863328f5bc1a31472 100644 --- a/src/app/search-multiple/containers/position.component.ts +++ b/src/app/search-multiple/containers/position.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; -import { Dataset } from '../../metamodel/model'; +import { Dataset, Project } from '../../metamodel/model'; import { SearchMultipleQueryParams } from "../store/model"; import { ConeSearch } from "../../shared/cone-search/store/model"; import * as searchMultipleActions from '../store/search-multiple.action'; @@ -29,18 +29,24 @@ export class PositionComponent implements OnInit { public datasetSearchMetaIsLoading: Observable<boolean>; public datasetSearchMetaIsLoaded: Observable<boolean>; public currentStep: Observable<string>; - public datasetList: Observable<Dataset[]>; public isValidConeSearch: Observable<boolean>; public coneSearch: Observable<ConeSearch>; + public projectList: Observable<Project[]>; + public datasetList: Observable<Dataset[]>; + public selectedDatasets: Observable<string[]>; + public noSelectedDatasets: Observable<boolean>; public queryParams: Observable<SearchMultipleQueryParams>; 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.datasetList = store.select(metamodelSelector.getDatasetList); this.isValidConeSearch = this.store.select(coneSearchSelector.getIsValidConeSearch); this.coneSearch = this.store.select(coneSearchSelector.getConeSearch); + this.projectList = store.select(metamodelSelector.getProjectList); + this.datasetList = store.select(metamodelSelector.getDatasetList); + this.selectedDatasets = store.select(searchMultipleSelector.getSelectedDatasets); + this.noSelectedDatasets = store.select(searchMultipleSelector.getNoSelectedDatasets); this.queryParams = this.store.select(searchMultipleSelector.getQueryParams); } diff --git a/src/app/search-multiple/store/search-multiple.action.ts b/src/app/search-multiple/store/search-multiple.action.ts index b3fa8fd36845e65124f2d011543b443d56bd8b03..08d96ecefd8556925659921ed53fe1bf203d958f 100644 --- a/src/app/search-multiple/store/search-multiple.action.ts +++ b/src/app/search-multiple/store/search-multiple.action.ts @@ -5,7 +5,7 @@ export const INIT_SELECTED_DATASETS = '[SearchMultiple] Init Selected Datasets'; export const CHANGE_STEP = '[SearchMultiple] Change Step'; export const POSITION_CHECKED = '[SearchMultiple] Position Checked'; export const DATASETS_CHECKED = '[SearchMultiple] Datasets Checked'; -export const ADD_DATASET = '[SearchMultiple] Add Dataset'; +export const UPDATE_SELECTED_DATASETS = '[SearchMultiple] Update Selected Datasets'; export class InitSearchByUrlAction implements Action { @@ -38,10 +38,10 @@ export class DatasetsCheckedAction implements Action { constructor(public payload: {} = null) { } } -export class AddDatasetAction implements Action { - readonly type = ADD_DATASET; +export class UpdateSelectedDatasetsAction implements Action { + readonly type = UPDATE_SELECTED_DATASETS; - constructor(public payload: string) { } + constructor(public payload: string[]) { } } export type Actions @@ -50,4 +50,4 @@ export type Actions | ChangeStepAction | PositionCheckedAction | DatasetsCheckedAction - | AddDatasetAction; + | UpdateSelectedDatasetsAction; diff --git a/src/app/search-multiple/store/search-multiple.reducer.ts b/src/app/search-multiple/store/search-multiple.reducer.ts index c722d698953d3cf38eb287c1ca03347359b052db..94358baf2d5629e04eaede739e7a01dbda055778 100644 --- a/src/app/search-multiple/store/search-multiple.reducer.ts +++ b/src/app/search-multiple/store/search-multiple.reducer.ts @@ -25,17 +25,15 @@ export const initialState: State = { export function reducer(state: State = initialState, action: actions.Actions): State { switch (action.type) { case actions.INIT_SELECTED_DATASETS: - const selectedDatasets: string[] = action.payload; return { ...state, - selectedDatasets + selectedDatasets: action.payload }; case actions.CHANGE_STEP: - const currentStep: string = action.payload; return { ...state, - currentStep + currentStep: action.payload }; case actions.POSITION_CHECKED: @@ -51,11 +49,10 @@ export function reducer(state: State = initialState, action: actions.Actions): S datasetsStepChecked: true }; - case actions.ADD_DATASET: - const dname: string = action.payload; + case actions.UPDATE_SELECTED_DATASETS: return { ...state, - selectedDatasets: [...state.selectedDatasets, dname] + selectedDatasets: action.payload }; default: diff --git a/src/app/search-multiple/store/search-multiple.selector.ts b/src/app/search-multiple/store/search-multiple.selector.ts index d6b974b0f2dd48476b2b99ae5b595e8576ca9a56..8198f5f4dea9771898759d9176f12e6ee7714388 100644 --- a/src/app/search-multiple/store/search-multiple.selector.ts +++ b/src/app/search-multiple/store/search-multiple.selector.ts @@ -36,12 +36,22 @@ export const getResultStepChecked = createSelector( searchMultiple.getResultStepChecked ); - export const getSelectedDatasets = createSelector( getSearchMultipleState, searchMultiple.getSelectedDatasets ); +export const getNoSelectedDatasets = createSelector( + getSelectedDatasets, + ( + selectedDatasets: string[]) => { + if (selectedDatasets.length === 0) { + return true; + } + return false; + } +); + export const getQueryParams = createSelector( getIsValidConeSearch, getConeSearch,