mirror of
https://github.com/Myxelium/Bridge-Multi.git
synced 2026-04-09 05:09:39 +00:00
Add pagination for advanced search
This commit is contained in:
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() }),
|
||||
|
||||
Reference in New Issue
Block a user