diff --git a/src/app/pages/data-catalogue/data-catalogue.module.ts b/src/app/pages/data-catalogue/data-catalogue.module.ts index c45c1fb4323c3fa9a96f2beac3ccb775a4a5d60d..66db9cc4d0ed269bf87f229b3a68a5dc5d993390 100644 --- a/src/app/pages/data-catalogue/data-catalogue.module.ts +++ b/src/app/pages/data-catalogue/data-catalogue.module.ts @@ -6,7 +6,8 @@ import { DataCatalogueRoutingModule } from './data-catalogue-routing.module'; import { SearchComponent } from './search/search.component'; import { DatasetComponent } from './dataset/dataset.component'; import { DataCatalogueComponent } from './data-catalogue.component'; -import { NbCardModule, NbFormFieldModule, NbIconModule, NbInputModule, NbListModule, NbSpinnerModule, NbTagModule } from '@nebular/theme'; +import { NbCardModule, NbFormFieldModule, NbIconModule, NbInputModule, NbListModule, NbSpinnerModule, NbTagModule, NbTooltipModule } from '@nebular/theme'; +import { NgxPaginationModule } from 'ngx-pagination'; @NgModule({ declarations: [DataCatalogueComponent, SearchComponent, DatasetComponent], @@ -19,6 +20,8 @@ import { NbCardModule, NbFormFieldModule, NbIconModule, NbInputModule, NbListMod NbSpinnerModule, NbListModule, NbCardModule, + NbTooltipModule, + NgxPaginationModule, DataCatalogueRoutingModule ] }) diff --git a/src/app/pages/data-catalogue/model/search-filter.ts b/src/app/pages/data-catalogue/model/search-filter.ts index c370c764f133a5787c6fa8f9dcc7e55cd721ac6a..8fab8ca06bb6fc41a4ab8e626b77bf30e4cd8e25 100644 --- a/src/app/pages/data-catalogue/model/search-filter.ts +++ b/src/app/pages/data-catalogue/model/search-filter.ts @@ -2,5 +2,8 @@ export class SearchFilter { field: string='ALL'; value: string=""; - constructor(){} + constructor(field?:string,value?:string){ + this.field=(field!=undefined)?field:'ALL'; + this.value=(value!=undefined)?value:""; + } } \ No newline at end of file diff --git a/src/app/pages/data-catalogue/model/search-request.ts b/src/app/pages/data-catalogue/model/search-request.ts index 8e27be0d08a59fd8fec4205deabce96761c14991..d8aaee96c175b93aa0a0493dee03993de54c2f3a 100644 --- a/src/app/pages/data-catalogue/model/search-request.ts +++ b/src/app/pages/data-catalogue/model/search-request.ts @@ -10,8 +10,8 @@ export class SearchRequest { live: boolean = false; euroVocFilter: SearchEuroVocFilter=new SearchEuroVocFilter(); sort: SortOption=new SortOption(); - rows: string='20'; - start: string='0'; + rows: number=20; + start: number=0; nodes?: number[]=[]; constructor(){} diff --git a/src/app/pages/data-catalogue/search/search.component.html b/src/app/pages/data-catalogue/search/search.component.html index af93238791cbc492ffe9edc8ba0cce0eb4b42f0b..52b6fc7160e38175e7b644ad408c28162d5c44b7 100644 --- a/src/app/pages/data-catalogue/search/search.component.html +++ b/src/app/pages/data-catalogue/search/search.component.html @@ -26,22 +26,42 @@ <div class="col-3"> <!-- Facets --> <nb-card *ngFor="let facet of searchResponse.facets" status="primary"> - <nb-card-header>{{facet.displayName}}</nb-card-header> + <nb-card-header class="d-flex justify-content-between"> + + {{facet.displayName}} + + <span *ngIf="facet.values.length>10" class="d-flex flex-row-reverse"> + <nb-icon *ngIf="getFacetsLimit(facet.displayName.toLowerCase())==10" icon="arrowhead-down-outline" (click)="setFacetsLimit(facet.displayName.toLowerCase(),facet.values.length)" + nbTooltip="Show all"></nb-icon> + <nb-icon *ngIf="getFacetsLimit(facet.displayName.toLowerCase())>10" icon="arrowhead-up-outline" (click)="setFacetsLimit(facet.displayName.toLowerCase(),10)" + nbTooltip="Show top 10"></nb-icon> + </span> + </nb-card-header> <nb-card-body> - <nb-list > - <nb-list-item *ngFor="let item of facet.values | slice:0:10"> - {{item.facet}} + <nb-list class="no-border"> + <nb-list-item *ngFor="let item of facet.values | slice:0:getFacetsLimit(facet.displayName.toLowerCase())" class="p-1 no-border"> + <a href="javascript:void(0)" (click)="getDatasetByFacet(facet.search_parameter,item.search_value)" + *ngIf="displayFacet(facet.search_parameter,item.search_value)">{{item.facet}}</a> </nb-list-item> </nb-list> </nb-card-body> </nb-card> </div> <div class="col-9"> + <div class="row m-1"> + <pagination-controls (pageChange)="pageChanged($event)"> + </pagination-controls> + </div> + <div class="row m-1"> + <nb-tag-list (tagRemove)="onFilterRemove($event)" > + <nb-tag appearance="outline" status="primary" *ngFor="let filter of filtersTags" [text]="filter" removable></nb-tag> + </nb-tag-list> + </div> <!-- results --> - <nb-card *ngFor="let dataset of searchResponse.results" size="tiny"> + <nb-card *ngFor="let dataset of searchResponse.results | paginate: { itemsPerPage: searchRequest.rows, currentPage: page, totalItems: searchResponse.count }" class="minicard"> <nb-card-header>{{dataset.title}}</nb-card-header> - <nb-card-body> - <p>{{dataset.description}}</p> + <nb-card-body class="content-truncated"> + <span class="truncated">{{dataset.description}}</span> </nb-card-body> <nb-card-footer> <nb-tag-list size="small"> @@ -50,91 +70,13 @@ </nb-tag-list> </nb-card-footer> </nb-card> - </div> + <div class="row m-1"> + <pagination-controls (pageChange)="pageChanged($event)"> + </pagination-controls> + </div> + </div> </div> -</div> -<!-- <div class="card-row"> - <div class="card-col"> - <nb-card size="tiny"> - <nb-card-header>Tiny card</nb-card-header> - </nb-card> - <nb-card size="tiny"> - <nb-card-header>Tiny card</nb-card-header> - </nb-card> - </div> - <div class="card-col"> - <nb-card size="medium"> - <nb-card-header>Medium card</nb-card-header> - </nb-card> - </div> - </div> - - <div class="card-row"> - <div class="card-col"> - <nb-card size="tiny"> - <nb-card-header>Tiny card</nb-card-header> - </nb-card> - <nb-card size="small"> - <nb-card-header>Small card</nb-card-header> - </nb-card> - </div> - <div class="card-col"> - <nb-card size="large"> - <nb-card-header>Large card</nb-card-header> - </nb-card> - </div> - </div> - - <div class="card-row"> - <div class="card-col"> - <nb-card size="tiny"> - <nb-card-header>Tiny card</nb-card-header> - </nb-card> - <nb-card size="medium"> - <nb-card-header>Medium card</nb-card-header> - </nb-card> - </div> - <div class="card-col"> - <nb-card size="giant"> - <nb-card-header>Giant card</nb-card-header> - </nb-card> - </div> - </div> - - <div class="card-row"> - <div class="card-col"> - <nb-card size="tiny"> - <nb-card-header>Tiny card</nb-card-header> - </nb-card> - <nb-card size="tiny"> - <nb-card-header>Tiny card</nb-card-header> - </nb-card> - <nb-card size="tiny"> - <nb-card-header>Tiny card</nb-card-header> - </nb-card> - </div> - <div class="card-col"> - <nb-card size="giant"> - <nb-card-header>Giant card</nb-card-header> - </nb-card> - </div> - </div> - - <div class="card-row"> - <div class="card-col"> - <nb-card size="small"> - <nb-card-header>Small card</nb-card-header> - </nb-card> - <nb-card size="small"> - <nb-card-header>Small card</nb-card-header> - </nb-card> - </div> - <div class="card-col"> - <nb-card size="giant"> - <nb-card-header>Giant card</nb-card-header> - </nb-card> - </div> - </div> --> \ No newline at end of file +</div> \ No newline at end of file diff --git a/src/app/pages/data-catalogue/search/search.component.scss b/src/app/pages/data-catalogue/search/search.component.scss index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d5e5beca01612459d3b769e1e2865eed4c9f0850 100644 --- a/src/app/pages/data-catalogue/search/search.component.scss +++ b/src/app/pages/data-catalogue/search/search.component.scss @@ -0,0 +1,23 @@ +.no-border{ + border: none; + :first-child{ + border: none; + } +} + +.truncate { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.content-truncated { + width:100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.minicard{ + height:unset; +} \ No newline at end of file diff --git a/src/app/pages/data-catalogue/search/search.component.ts b/src/app/pages/data-catalogue/search/search.component.ts index abb232d6bb9521fb24c2e3e90215cfabfdf7e5b8..657c651f61a555994951dc874f1d370d0e8e7805 100644 --- a/src/app/pages/data-catalogue/search/search.component.ts +++ b/src/app/pages/data-catalogue/search/search.component.ts @@ -2,6 +2,7 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { NbTagComponent, NbTagInputAddEvent } from '@nebular/theme'; import { DCATDataset,FormatCount } from '../model/dcatdataset'; import { ODMSCatalogueInfo } from '../model/odmscatalogue-info'; +import { SearchFilter } from '../model/search-filter'; import { SearchRequest } from '../model/search-request'; import { SearchResult } from '../model/search-result'; import { RestAPIService } from '../services/rest-api.service'; @@ -24,41 +25,85 @@ export class SearchComponent implements OnInit { loading=false; - trees: Set<string> = new Set(['asd']); + facetLimits={}; + page=1; + + trees: Array<string> = ['asd']; + filtersTags: Array<string>= []; ngOnInit(): void { this.loading=true this.restApi.getCataloguesInfo().subscribe(infos =>{ this.cataloguesInfos = infos; this.searchRequest.nodes = infos.map(x=>x.id) - this.restApi.searchDatasets(this.searchRequest).subscribe( - res=>{ - this.searchResponse=res - this.searchResponse.results.map((x:DCATDataset)=>{ this.fillDistributionFormats(x) }) - this.loading=false; - }, - err=>{ - console.log(err); - this.loading=false; - }); + this.loading=false + this.searchDataset() },err=>{ console.log(err); this.loading=false; }) } + pageChanged($event:number){ + this.page=$event; + this.searchRequest.start=($event-1)*this.searchRequest.rows; + this.searchDataset() + } + + searchDataset(){ + this.loading=true + this.filtersTags=[]; + console.log(this.searchRequest.filters) + + this.searchRequest.filters.forEach(x=>{ + if(x.field!='ALL'){ + let values = x.value.split(',') + let name=x.field; + let index = this.searchResponse.facets.findIndex(x=> x.search_parameter===name) + if(index>=0){ + name=this.searchResponse.facets[index].displayName; + } + values.forEach(y=> this.filtersTags.push(name+": "+y)) + } + }) + + this.restApi.searchDatasets(this.searchRequest).subscribe( + res=>{ + this.searchResponse=res + this.searchResponse.results.map((x:DCATDataset)=>{ this.processDataset(x) }) + this.loading=false; + }, + err=>{ + console.log(err); + this.loading=false; + }); + } + onTagRemove(tagToRemove: NbTagComponent): void { - this.trees.delete(tagToRemove.text); + //this.trees.delete(tagToRemove.text); } onTagAdd({ value, input }: NbTagInputAddEvent): void { - if (value) { - this.trees.add(value) + // if (value) { + // this.trees.add(value) + // } + // input.nativeElement.value = ''; + } + + + getFacetsLimit(facet){ + if(this.facetLimits[facet]==undefined){ + this.facetLimits[facet]=10; } - input.nativeElement.value = ''; + return this.facetLimits[facet]; + } + + setFacetsLimit(facet,value){ + this.facetLimits[facet]=value; } - fillDistributionFormats(dataset:DCATDataset):DCATDataset{ + + processDataset(dataset:DCATDataset):DCATDataset{ let tmp=[]; dataset.distributionFormats=[]; for(let d of dataset.distributions){ @@ -72,7 +117,12 @@ export class SearchComponent implements OnInit { dataset.distributionFormats[tmp.indexOf(d.format)].count++; } } - console.log(dataset.distributionFormats) + + dataset.description = dataset.description.replace(/\*/g,'').replace(/\\n/g,'') + .replace(/\(http.*\)/g,'').replace(/##\s*/g,'') + .replace(/<.*>(.*)<\/.*>/g,'$1') + .replace(/>/g,'').replace(/\[|\]/g,'') + return dataset; } @@ -112,4 +162,48 @@ export class SearchComponent implements OnInit { return 'default'; } } + + onFilterRemove(filter: NbTagComponent): void { + let tmp=filter.text.split(': '); + let name = tmp[0]; + let facetIndex = this.searchResponse.facets.findIndex(x=>x.displayName==name) + if(facetIndex>=0){ + name=this.searchResponse.facets[facetIndex].search_parameter; + } + let index = this.searchRequest.filters.findIndex(x=> x.field==name); + let filterTag = this.searchRequest.filters[index]; + this.searchRequest.filters[index].value=filterTag.value.split(',').filter(x=> x!=tmp[1]).join(','); + if(this.searchRequest.filters[index].value==''){ + this.searchRequest.filters.splice(index,1); + } + this.searchDataset() + } + + getDatasetByFacet(search_parameter,newValue){ + this.page=1; + this.searchRequest.start=0; + let index = this.searchRequest.filters.findIndex(x=> x.field===search_parameter); + if(index<0){ + this.searchRequest.filters.push(new SearchFilter(search_parameter,newValue)); + }else{ + let filter=this.searchRequest.filters[index]; + this.searchRequest.filters.splice(index,1) + let tmp=filter.value.split(','); + tmp.push(newValue); + filter.value=tmp.join(','); + this.searchRequest.filters.push(filter); + } + this.searchDataset() + } + + displayFacet(search_parameter,value){ + let index = this.searchRequest.filters.findIndex(x=> x.field===search_parameter); + if(index<0) return true; + else{ + let values=this.searchRequest.filters[index].value.split(','); + let vIndex = values.findIndex(x=>x===value) + if(vIndex<0) return true; + } + return false; + } }