Add search result sorting

This commit is contained in:
Patrick Gebhardt 2020-06-23 16:12:41 +02:00
parent e948243417
commit f9157e8e61
5 changed files with 103 additions and 4 deletions

View File

@ -3,7 +3,7 @@
src="https://travopti.de/api/v1/regions/{{result.region_id}}/image">
<div class="result-title">
<div class="result-name">
<span class="result-name">{{result.name}}</span>
<span class="result-name">{{result.name}}<span *ngIf="debug"> ({{result.score}})</span></span>
<span class="result-country">| {{result.country}}</span>
</div>
<app-bookmark-button [region]="result"></app-bookmark-button>
@ -28,7 +28,7 @@
<span>{{PROPERTY_VIS_DEF[score.type] ? PROPERTY_VIS_DEF[score.type].unit : ''}}</span>
</div>
</td>
<td>
<td *ngIf="debug">
<div class="cell">
<span>({{score.score}})</span>
</div>

View File

@ -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;

View File

@ -3,9 +3,25 @@
<span #result></span>
<div *ngIf="results && results.length > 0">
<h2>Results ({{results.length}}):</h2>
<div class="result-header">
<span class="title">Results ({{results.length}})</span>
<div class="sorting">
<button (click)="sortDes = !sortDes; onSortDirChange()" mat-icon-button>
<mat-icon>{{sortDes ? 'arrow_downwards' : 'arrow_upwards'}}</mat-icon>
</button>
<mat-form-field>
<mat-label>Sort by</mat-label>
<mat-select (selectionChange)="onSortChange()" [(ngModel)]="sortBy">
<mat-option *ngFor="let option of sortOptions" [value]="option.property">
{{option.name|translate}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
<div class="result-container">
<app-result (click)="onResultClick(result)" *ngFor="let result of results" [result]="result"></app-result>
<app-result (click)="onResultClick(result)" *ngFor="let result of results" [debug]="debug"
[result]="result"></app-result>
</div>
</div>

View File

@ -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;

View File

@ -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;
}
}
}