mirror of
https://github.com/Myxelium/Bridge-Multi.git
synced 2026-07-07 10:35:09 +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
|
const table = this.resultTableDiv.nativeElement
|
||||||
if (this.router.url === '/browse' && table.scrollHeight - (table.scrollTop + table.clientHeight) < 100) {
|
if (this.router.url === '/browse' && table.scrollHeight - (table.scrollTop + table.clientHeight) < 100) {
|
||||||
// Scrolled near the bottom of the table
|
// Scrolled near the bottom of the table
|
||||||
if (this.searchService.areMorePages && !this.searchService.searchLoading) {
|
this.searchService.getNextSearchPage()
|
||||||
this.searchService.search(this.searchService.searchControl.value || '*', true).subscribe()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ export class SearchBarComponent implements OnInit, AfterViewInit {
|
|||||||
maxMaxNPS: null as number | null,
|
maxMaxNPS: null as number | null,
|
||||||
minYear: null as number | null,
|
minYear: null as number | null,
|
||||||
maxYear: 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(''),
|
hash: this.fb.nonNullable.control(''),
|
||||||
trackHash: this.fb.nonNullable.control(''),
|
trackHash: this.fb.nonNullable.control(''),
|
||||||
hasSoloSections: null as boolean | null,
|
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))) {
|
if (control.value && isNaN(Date.parse(control.value))) {
|
||||||
return { 'dateVaidator': true }
|
return { 'dateValidator': true }
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export class SearchService {
|
|||||||
public newSearch = new EventEmitter<Partial<SearchResult>>()
|
public newSearch = new EventEmitter<Partial<SearchResult>>()
|
||||||
public updateSearch = new EventEmitter<Partial<SearchResult>>()
|
public updateSearch = new EventEmitter<Partial<SearchResult>>()
|
||||||
public isDefaultSearch = true
|
public isDefaultSearch = true
|
||||||
|
public lastAdvancedSearch: AdvancedSearch
|
||||||
|
|
||||||
public groupedSongs: ChartData[][]
|
public groupedSongs: ChartData[][]
|
||||||
|
|
||||||
@@ -141,12 +142,23 @@ export class SearchService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public advancedSearch(search: AdvancedSearch) {
|
public advancedSearch(search: AdvancedSearch, nextPage = false) {
|
||||||
this.searchLoading = true
|
this.searchLoading = true
|
||||||
this.isDefaultSearch = false
|
this.isDefaultSearch = false
|
||||||
|
this.lastAdvancedSearch = search
|
||||||
|
|
||||||
|
if (nextPage) {
|
||||||
|
this.currentPage++
|
||||||
|
} else {
|
||||||
|
this.currentPage = 1
|
||||||
|
}
|
||||||
|
|
||||||
let retries = 10
|
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) => {
|
catchError((err, caught) => {
|
||||||
if (err.status === 400 || retries-- <= 0) {
|
if (err.status === 400 || retries-- <= 0) {
|
||||||
this.searchLoading = false
|
this.searchLoading = false
|
||||||
@@ -159,13 +171,15 @@ export class SearchService {
|
|||||||
tap(response => {
|
tap(response => {
|
||||||
this.searchLoading = false
|
this.searchLoading = false
|
||||||
|
|
||||||
// Don't reload results if they are the same
|
if (!nextPage) {
|
||||||
if (this.groupedSongs
|
// Don't reload results if they are the same
|
||||||
&& _.xorBy(this.songsResponse!.data, response.data, r => r.chartId).length === 0
|
if (this.groupedSongs
|
||||||
&& this.songsResponse!.found === response.found) {
|
&& _.xorBy(this.songsResponse!.data, response.data, r => r.chartId).length === 0
|
||||||
return
|
&& this.songsResponse!.found === response.found) {
|
||||||
} else {
|
return
|
||||||
this.groupedSongs = []
|
} else {
|
||||||
|
this.groupedSongs = []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.songsResponse = response
|
this.songsResponse = response
|
||||||
@@ -177,8 +191,22 @@ export class SearchService {
|
|||||||
.value()
|
.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'
|
import { difficulties, drumTypeNames, instruments } from './UtilFunctions.js'
|
||||||
|
|
||||||
|
export const sources = ['api'] as const
|
||||||
|
|
||||||
export const GeneralSearchSchema = z.object({
|
export const GeneralSearchSchema = z.object({
|
||||||
search: z.string(),
|
search: z.string(),
|
||||||
per_page: z.number().positive().lte(250, 'Getting more than 250 results at a time is not supported').optional(),
|
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(),
|
instrument: z.enum(instruments).nullable(),
|
||||||
difficulty: z.enum(difficulties).nullable(),
|
difficulty: z.enum(difficulties).nullable(),
|
||||||
drumType: z.enum(drumTypeNames).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() }),
|
name: z.object({ value: z.string(), exact: z.boolean(), exclude: z.boolean() }),
|
||||||
artist: 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() }),
|
album: z.object({ value: z.string(), exact: z.boolean(), exclude: z.boolean() }),
|
||||||
|
|||||||
Reference in New Issue
Block a user