Add pagination for advanced search

This commit is contained in:
Geomitron
2024-07-27 21:23:42 -05:00
parent ed1aada613
commit b6de0513dc
4 changed files with 47 additions and 16 deletions

View File

@@ -124,9 +124,7 @@ export class ResultTableComponent implements OnInit {
const table = this.resultTableDiv.nativeElement
if (this.router.url === '/browse' && table.scrollHeight - (table.scrollTop + table.clientHeight) < 100) {
// Scrolled near the bottom of the table
if (this.searchService.areMorePages && !this.searchService.searchLoading) {
this.searchService.search(this.searchService.searchControl.value || '*', true).subscribe()
}
this.searchService.getNextSearchPage()
}
}
}

View File

@@ -178,7 +178,7 @@ export class SearchBarComponent implements OnInit, AfterViewInit {
maxMaxNPS: null as number | null,
minYear: null as number | null,
maxYear: null as number | null,
modifiedAfter: this.fb.nonNullable.control('', { validators: dateVaidator }),
modifiedAfter: this.fb.nonNullable.control('', { validators: dateValidator }),
hash: this.fb.nonNullable.control(''),
trackHash: this.fb.nonNullable.control(''),
hasSoloSections: null as boolean | null,
@@ -231,9 +231,9 @@ export class SearchBarComponent implements OnInit, AfterViewInit {
}
}
function dateVaidator(control: AbstractControl) {
function dateValidator(control: AbstractControl) {
if (control.value && isNaN(Date.parse(control.value))) {
return { 'dateVaidator': true }
return { 'dateValidator': true }
}
return null
}

View File

@@ -22,6 +22,7 @@ export class SearchService {
public newSearch = new EventEmitter<Partial<SearchResult>>()
public updateSearch = new EventEmitter<Partial<SearchResult>>()
public isDefaultSearch = true
public lastAdvancedSearch: AdvancedSearch
public groupedSongs: ChartData[][]
@@ -141,12 +142,23 @@ export class SearchService {
)
}
public advancedSearch(search: AdvancedSearch) {
public advancedSearch(search: AdvancedSearch, nextPage = false) {
this.searchLoading = true
this.isDefaultSearch = false
this.lastAdvancedSearch = search
if (nextPage) {
this.currentPage++
} else {
this.currentPage = 1
}
let retries = 10
return this.http.post<{ data: SearchResult['data']; found: number }>(`${environment.apiUrl}/search/advanced`, search).pipe(
return this.http.post<{ data: SearchResult['data']; found: number }>(`${environment.apiUrl}/search/advanced`, {
per_page: resultsPerPage,
page: this.currentPage,
...search,
}).pipe(
catchError((err, caught) => {
if (err.status === 400 || retries-- <= 0) {
this.searchLoading = false
@@ -159,13 +171,15 @@ export class SearchService {
tap(response => {
this.searchLoading = false
// Don't reload results if they are the same
if (this.groupedSongs
&& _.xorBy(this.songsResponse!.data, response.data, r => r.chartId).length === 0
&& this.songsResponse!.found === response.found) {
return
} else {
this.groupedSongs = []
if (!nextPage) {
// Don't reload results if they are the same
if (this.groupedSongs
&& _.xorBy(this.songsResponse!.data, response.data, r => r.chartId).length === 0
&& this.songsResponse!.found === response.found) {
return
} else {
this.groupedSongs = []
}
}
this.songsResponse = response
@@ -177,8 +191,22 @@ export class SearchService {
.value()
)
this.newSearch.emit(response)
if (nextPage) {
this.updateSearch.emit(response)
} else {
this.newSearch.emit(response)
}
})
)
}
public getNextSearchPage() {
if (this.areMorePages && !this.searchLoading) {
if (this.isDefaultSearch) {
this.search(this.searchControl.value || '*', true).subscribe()
} else {
this.advancedSearch(this.lastAdvancedSearch, true).subscribe()
}
}
}
}

View File

@@ -2,6 +2,8 @@ import { z } from 'zod'
import { difficulties, drumTypeNames, instruments } from './UtilFunctions.js'
export const sources = ['api'] as const
export const GeneralSearchSchema = z.object({
search: z.string(),
per_page: z.number().positive().lte(250, 'Getting more than 250 results at a time is not supported').optional(),
@@ -19,6 +21,9 @@ export const AdvancedSearchSchema = z.object({
instrument: z.enum(instruments).nullable(),
difficulty: z.enum(difficulties).nullable(),
drumType: z.enum(drumTypeNames).nullable(),
source: z.enum(sources).optional(),
per_page: z.number().positive().lte(250, 'Getting more than 250 results at a time is not supported').optional(),
page: z.number().positive().optional(),
name: z.object({ value: z.string(), exact: z.boolean(), exclude: z.boolean() }),
artist: z.object({ value: z.string(), exact: z.boolean(), exclude: z.boolean() }),
album: z.object({ value: z.string(), exact: z.boolean(), exclude: z.boolean() }),