diff --git a/frontend/src/app/components/result/result.component.html b/frontend/src/app/components/result/result.component.html index 775f78b..422e9e9 100644 --- a/frontend/src/app/components/result/result.component.html +++ b/frontend/src/app/components/result/result.component.html @@ -3,7 +3,7 @@ src="https://travopti.de/api/v1/regions/{{result.region_id}}/image">
- {{result.name}} + {{result.name}} ({{result.score}}) | {{result.country}}
@@ -28,7 +28,7 @@ {{PROPERTY_VIS_DEF[score.type] ? PROPERTY_VIS_DEF[score.type].unit : ''}}
- +
({{score.score}})
diff --git a/frontend/src/app/components/result/result.component.ts b/frontend/src/app/components/result/result.component.ts index ce4e21c..8f70ce8 100644 --- a/frontend/src/app/components/result/result.component.ts +++ b/frontend/src/app/components/result/result.component.ts @@ -12,6 +12,9 @@ export class ResultComponent implements OnInit { @Input() result: Result; + @Input() + debug = false; + /** Contains the visual definitions */ readonly PROPERTY_VIS_DEF = REGION_PARAM_VIS; diff --git a/frontend/src/app/containers/search/search.component.html b/frontend/src/app/containers/search/search.component.html index f1c3247..b8079b7 100644 --- a/frontend/src/app/containers/search/search.component.html +++ b/frontend/src/app/containers/search/search.component.html @@ -3,9 +3,25 @@
-

Results ({{results.length}}):

+
+ Results ({{results.length}}) +
+ + + Sort by + + + {{option.name|translate}} + + + +
+
- +
diff --git a/frontend/src/app/containers/search/search.component.scss b/frontend/src/app/containers/search/search.component.scss index 097ba9d..82a2f60 100644 --- a/frontend/src/app/containers/search/search.component.scss +++ b/frontend/src/app/containers/search/search.component.scss @@ -8,6 +8,24 @@ } } +.result-header { + display: flex; + align-items: center; + margin: 1rem 0; + + .title { + flex: 1 1 auto; + font-size: 1.5rem; + font-weight: bold; + } + + .sorting { + display: flex; + flex-direction: row; + align-items: center; + } +} + .result-container { display: flex; flex-direction: column; diff --git a/frontend/src/app/containers/search/search.component.ts b/frontend/src/app/containers/search/search.component.ts index 6950761..f246d00 100644 --- a/frontend/src/app/containers/search/search.component.ts +++ b/frontend/src/app/containers/search/search.component.ts @@ -3,6 +3,13 @@ import {ActivatedRoute, Router} from '@angular/router'; import {Result} from '../../interfaces/result.interface'; import {SearchService} from '../../services/search.service'; +interface SortOption { + name: string; + property: string; + descending?: boolean; + isScore?: boolean; +} + @Component({ selector: 'app-search', templateUrl: './search.component.html', @@ -10,9 +17,20 @@ import {SearchService} from '../../services/search.service'; }) export class SearchComponent implements OnInit { + /** Current base64 encoded query */ queryString: string; + /** Current results */ results: Result[]; + /** The property to sort by */ + sortBy = 'score'; + /** Sort descending */ + sortDes = true; + /** Available sort options */ + sortOptions: SortOption[] = []; + + debug = false; + @ViewChild('result', {static: false}) resultDiv: ElementRef; @@ -22,6 +40,7 @@ export class SearchComponent implements OnInit { async ngOnInit() { this.route.queryParams.subscribe(async params => { this.queryString = params.q; + this.debug = params.debug || false; this.results = undefined; if (!this.queryString || this.queryString.length === 0) { @@ -31,10 +50,53 @@ export class SearchComponent implements OnInit { this.results = await this.ss.executeSearch(this.queryString); this.resultDiv.nativeElement.scrollIntoView({behavior: 'smooth', block: 'start'}); + + this.sortOptions = [ + {name: 'Relevance', property: 'score', descending: true}, + {name: 'Name', property: 'name'} + ]; + + if (this.results.length > 0) { + this.results[0].scores.forEach(({type}) => { + this.sortOptions.push({name: type, property: type, isScore: true}); + }); + } + }); } onResultClick(result: Result) { this.router.navigate(['/region', result.region_id]).catch(console.log); } + + onSortDirChange() { + const option = this.sortOptions.find(i => i.property === this.sortBy); + this.sortResults(option, this.sortDes); + } + + onSortChange() { + const option = this.sortOptions.find(i => i.property === this.sortBy); + this.sortDes = option.descending; + this.onSortDirChange(); + } + + /** + * Sorts the results array by the given property. + * @param property The property to sort by + * @param isScore If the property is in scores + * @param descending Sort descending instead of ascending + */ + private sortResults({property, isScore}: SortOption, descending: boolean) { + this.results = this.results.sort(isScore ? sortByScore : sortByPorperty); + + function sortByPorperty(a: Result, b: Result): number { + const result = a[property] > b[property] ? 1 : -1; + return descending ? result * -1 : result; + } + + function sortByScore(a: Result, b: Result): number { + const result = a.scores.find(i => i.type === property).value > b.scores.find(i => i.type === property).value ? 1 : -1; + return descending ? result * -1 : result; + } + } }