182 lines
8.4 KiB
HTML
182 lines
8.4 KiB
HTML
<div class="main term">
|
|
<h1><span class="board">/k/</span> - Advanced Search</h1>
|
|
|
|
<ng-container *ngIf="this.isLoadingSchema; else searchPanel">
|
|
<div class="text-center">
|
|
<p>Loading schema...</p>
|
|
</div>
|
|
</ng-container>
|
|
<ng-template #searchPanel>
|
|
<fieldset>
|
|
<legend>Table columns</legend>
|
|
<ng-container *ngFor="let category of ['user', 'beatmap', 'score', 'metrics']">
|
|
<fieldset class="mb-2">
|
|
<legend>{{ category }} <button (click)="this.selectEntireFieldCategory(category)">Select all</button> <button (click)="this.deselectEntireFieldCategory(category)">Deselect all</button></legend>
|
|
<ng-container *ngFor="let field of fields">
|
|
<div *ngIf="field.category === category">
|
|
<label>
|
|
<input type="checkbox" [(ngModel)]="field.active" (change)="this.saveSettingsToLocalStorage()"/>
|
|
{{ field.name }} <span class="text-muted" style="margin-left: 6px">{{ field.description }}</span>
|
|
</label>
|
|
</div>
|
|
</ng-container>
|
|
</fieldset>
|
|
</ng-container>
|
|
|
|
</fieldset>
|
|
|
|
<div class="search-container mt-2" *ngIf="this.queries">
|
|
<app-query-builder [queries]="this.queries" [fields]="fields"></app-query-builder>
|
|
</div>
|
|
|
|
<fieldset class="mt-2" *ngIf="this.sortingOrder">
|
|
<legend>sorting</legend>
|
|
|
|
<select>
|
|
<ng-container *ngFor="let category of ['user', 'beatmap', 'score', 'metrics']">
|
|
<optgroup label="{{ category }}">
|
|
<ng-container *ngFor="let field of fields">
|
|
<ng-container *ngIf="field.category === category">
|
|
<option
|
|
[value]="field.name"
|
|
(click)="this.sortingOrder.field = field.name"
|
|
[selected]="field.name == this.sortingOrder.field"
|
|
>{{ field.name }}
|
|
</option>
|
|
</ng-container>
|
|
</ng-container>
|
|
</optgroup>
|
|
</ng-container>
|
|
</select>
|
|
<label style="margin-left: 8px">
|
|
<input type="radio" name="sortingOrder" [(ngModel)]="this.sortingOrder.order" value="ASC" />
|
|
↑ ASC
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="sortingOrder" [(ngModel)]="this.sortingOrder.order" value="DESC" />
|
|
↓ DESC
|
|
</label>
|
|
</fieldset>
|
|
|
|
<div class="text-center mt-2">
|
|
<button (click)="exportSettings()">Export settings</button>
|
|
<button (click)="fileInput.click()" style="margin-left: 5px">Import settings</button>
|
|
<input type="file" #fileInput style="display: none" (change)="uploadSettingsFile($event)" accept=".json">
|
|
</div>
|
|
<div class="text-center mt-1">
|
|
<button (click)="search()" [disabled]="this.isLoading" class="mb-2" style="font-size: 18px">Search</button>
|
|
</div>
|
|
|
|
<ng-container *ngIf="this.isLoading">
|
|
<div class="text-center">
|
|
<p>Loading <app-cute-loading></app-cute-loading></p>
|
|
<p>please be patient - the database is working hard!</p>
|
|
</div>
|
|
</ng-container>
|
|
|
|
<div class="text-center alert-error" *ngIf="this.isError">
|
|
<p>Looks like something went wrong... :(</p>
|
|
<p>I'll look into what caused the error - but feel free to get in touch.</p>
|
|
</div>
|
|
|
|
<ng-container *ngIf="response">
|
|
<ng-container *ngIf="response.scores.length <= 0">
|
|
<div class="text-center alert-error">
|
|
<p>No results for your query - try different parameters.</p>
|
|
</div>
|
|
</ng-container>
|
|
|
|
<ng-container *ngIf="response.scores.length > 0">
|
|
<fieldset class="mb-2">
|
|
<legend>tools</legend>
|
|
<div class="text-center">
|
|
<button (click)="this.downloadFilesService.downloadCSV(response.scores, getColumns(), 'nise-search')">Download .csv</button>
|
|
<button (click)="this.downloadFilesService.downloadJSON(response.scores, 'nise-search')">Download .json</button>
|
|
<button (click)="this.downloadFilesService.downloadXLSX(response.scores, 'nise-search')">Download .xlsx</button>
|
|
</div>
|
|
</fieldset>
|
|
<div class="scrollable-table">
|
|
<table class="table-border">
|
|
<thead>
|
|
<tr>
|
|
<th *ngFor="let column of fields" [hidden]="!column.active" class="text-center">
|
|
{{ column.shortName }}
|
|
</th>
|
|
<th>Links</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr *ngFor="let entry of response.scores" class="score-entry">
|
|
<td *ngFor="let column of fields" [hidden]="!column.active" class="text-center" style="line-height: 32px">
|
|
<ng-container *ngIf="getValue(entry, column.name) !== null; else nullDisplay">
|
|
<ng-container *ngIf="column.type == 'number'">
|
|
{{ getValue(entry, column.name) | number }}
|
|
</ng-container>
|
|
<ng-container *ngIf="column.type == 'flag'">
|
|
<span class="flag" [title]="getValue(entry, column.name)">{{ countryCodeToFlag(getValue(entry, column.name)) }}</span>
|
|
</ng-container>
|
|
<ng-container *ngIf="column.type == 'grade'">
|
|
<app-osu-grade [grade]="getValue(entry, column.name)"></app-osu-grade>
|
|
</ng-container>
|
|
<ng-container *ngIf="column.type == 'datetime'">
|
|
{{ getValue(entry, column.name) }}
|
|
</ng-container>
|
|
<ng-container *ngIf="column.type == 'boolean'">
|
|
<ng-container *ngIf="getValue(entry, column.name) == true">
|
|
✓
|
|
</ng-container>
|
|
<ng-container *ngIf="getValue(entry, column.name) == false">
|
|
✗
|
|
</ng-container>
|
|
</ng-container>
|
|
<ng-container *ngIf="column.type == 'playtime'">
|
|
{{ formatDuration(getValue(entry, column.name)) }}
|
|
</ng-container>
|
|
<ng-container *ngIf="column.type == 'string'">
|
|
|
|
<ng-container *ngIf="column.name == 'user_username'; else stringField">
|
|
<a [href]="'/u/' + getValue(entry, column.name)" target="_blank">{{ getValue(entry, column.name) }}</a>
|
|
</ng-container>
|
|
<ng-template #stringField>
|
|
{{ getValue(entry, column.name) }}
|
|
</ng-template>
|
|
|
|
</ng-container>
|
|
</ng-container>
|
|
<ng-template #nullDisplay><code>null</code></ng-template>
|
|
</td>
|
|
<td class="text-center" style="line-height: 32px">
|
|
<a [href]="'/s/' + this.getId(entry)" target="_blank">
|
|
details
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="text-center mt-2">
|
|
<p>Total results: {{ response.pagination.totalResults | number }}</p>
|
|
<p>Page: {{ response.pagination.currentPage | number }} / {{ response.pagination.totalPages | number }}</p>
|
|
<div class="mb-2">
|
|
<button *ngIf="response.pagination.currentPage > 5" (click)="this.search(1)" style="margin-right: 5px">1</button>
|
|
<span *ngIf="response.pagination.currentPage > 6">... </span>
|
|
<button *ngFor="let page of [].constructor(Math.min(response.pagination.totalPages, 10)) | calculatePageRange:response.pagination.currentPage:response.pagination.totalPages; let i = index"
|
|
(click)="this.search(page)"
|
|
[disabled]="page == response.pagination.currentPage"
|
|
style="margin-right: 5px">
|
|
{{ page }}
|
|
</button>
|
|
<span *ngIf="response.pagination.currentPage < response.pagination.totalPages - 5">... </span>
|
|
<button *ngIf="response.pagination.currentPage < response.pagination.totalPages - 4" (click)="this.search(response.pagination.totalPages)" style="margin-right: 5px">{{ response.pagination.totalPages }}</button>
|
|
</div>
|
|
<button (click)="this.search(response.pagination.currentPage - 1)" [disabled]="response.pagination.currentPage == 1">← Previous</button>
|
|
<button (click)="this.search(response.pagination.currentPage + 1)" [disabled]="response.pagination.currentPage == response.pagination.totalPages" style="margin-left: 5px">Next →</button>
|
|
</div>
|
|
</ng-container>
|
|
|
|
</ng-container>
|
|
</ng-template>
|
|
|
|
</div>
|