From e20f27dafee4b07b7bb0641120acdc0cd03fde91 Mon Sep 17 00:00:00 2001 From: Geomitron <22552797+Geomitron@users.noreply.github.com> Date: Sun, 5 Jan 2025 17:44:22 -0600 Subject: [PATCH] Improve search result sorting --- .../result-table/result-table.component.html | 4 +- .../result-table/result-table.component.ts | 49 ++++--------------- .../browse/search-bar/search-bar.component.ts | 1 + .../app/core/services/search.service.ts | 11 +++++ src-shared/interfaces/search.interface.ts | 9 ++++ src-shared/search-api.ts | 9 ++++ 6 files changed, 40 insertions(+), 43 deletions(-) diff --git a/src-angular/app/components/browse/result-table/result-table.component.html b/src-angular/app/components/browse/result-table/result-table.component.html index 5c73ac2..d5ce6a9 100644 --- a/src-angular/app/components/browse/result-table/result-table.component.html +++ b/src-angular/app/components/browse/result-table/result-table.component.html @@ -30,9 +30,7 @@ Length (min) - - Difficulty - + Difficulty diff --git a/src-angular/app/components/browse/result-table/result-table.component.ts b/src-angular/app/components/browse/result-table/result-table.component.ts index 92ef1b9..cd02daf 100644 --- a/src-angular/app/components/browse/result-table/result-table.component.ts +++ b/src-angular/app/components/browse/result-table/result-table.component.ts @@ -1,7 +1,6 @@ import { Component, ElementRef, EventEmitter, HostBinding, HostListener, OnInit, Output, QueryList, ViewChild, ViewChildren } from '@angular/core' import { Router } from '@angular/router' -import _ from 'lodash' import { SettingsService } from 'src-angular/app/core/services/settings.service' import { ChartData } from 'src-shared/interfaces/search.interface' @@ -23,7 +22,7 @@ export class ResultTableComponent implements OnInit { activeSong: ChartData[] | null = null sortDirection: 'asc' | 'desc' = 'asc' - sortColumn: 'name' | 'artist' | 'album' | 'genre' | 'year' | 'charter' | 'length' | 'difficulty' | null = null + sortColumn: 'name' | 'artist' | 'album' | 'genre' | 'year' | 'charter' | 'length' | null = null constructor( public searchService: SearchService, @@ -36,13 +35,9 @@ export class ResultTableComponent implements OnInit { this.searchService.newSearch.subscribe(() => { this.resultTableDiv.nativeElement.scrollTop = 0 this.activeSong = null - this.sortDirection = 'asc' - this.sortColumn = null - this.updateSort() setTimeout(() => this.tableScrolled(), 0) }) this.searchService.updateSearch.subscribe(() => { - this.updateSort() setTimeout(() => this.tableScrolled(), 0) }) } @@ -62,47 +57,21 @@ export class ResultTableComponent implements OnInit { } } - onColClicked(column: 'name' | 'artist' | 'album' | 'genre' | 'year' | 'charter' | 'length' | 'difficulty') { + onColClicked(column: 'name' | 'artist' | 'album' | 'genre' | 'year' | 'charter' | 'length') { if (this.songs.length === 0) { return } if (this.sortColumn !== column) { this.sortColumn = column this.sortDirection = 'asc' - } else if (this.sortDirection === 'desc') { - this.sortDirection = 'asc' - } else { + } else if (this.sortDirection === 'asc') { this.sortDirection = 'desc' - } - this.updateSort() - } - - private updateSort() { - const col = this.sortColumn - if (col !== null) { - console.log(this.getSortColumn()) - const groupedSongs = _.orderBy(this.searchService.groupedSongs, s => _.get(s[0], this.getSortColumn()), this.sortDirection) - this.searchService.groupedSongs = groupedSongs - } - } - private getSortColumn(): keyof ChartData { - if (this.sortColumn === 'length') { - return 'notesData.effectiveLength' as keyof ChartData - } else if (this.sortColumn === 'difficulty') { - switch (this.searchService.instrument.value) { - case 'guitar': return 'diff_guitar' - case 'guitarcoop': return 'diff_guitar_coop' - case 'rhythm': return 'diff_rhythm' - case 'bass': return 'diff_bass' - case 'drums': return 'diff_drums' - case 'keys': return 'diff_keys' - case 'guitarghl': return 'diff_guitarghl' - case 'guitarcoopghl': return 'diff_guitar_coop_ghl' - case 'rhythmghl': return 'diff_rhythm_ghl' - case 'bassghl': return 'diff_bassghl' - default: throw 'Invalid instrument' - } } else { - return this.sortColumn! + this.sortDirection = 'asc' + this.sortColumn = null } + + this.searchService.sortColumn = this.sortColumn + this.searchService.sortDirection = this.sortDirection + this.searchService.reloadSearch() } get allSelected() { diff --git a/src-angular/app/components/browse/search-bar/search-bar.component.ts b/src-angular/app/components/browse/search-bar/search-bar.component.ts index 10cf117..2730e1d 100644 --- a/src-angular/app/components/browse/search-bar/search-bar.component.ts +++ b/src-angular/app/components/browse/search-bar/search-bar.component.ts @@ -224,6 +224,7 @@ export class SearchBarComponent implements OnInit, AfterViewInit { instrument: this.instrument, difficulty: this.difficulty, drumType: this.drumType, + sort: this.searchService.sortColumn !== null ? { type: this.searchService.sortColumn, direction: this.searchService.sortDirection } : null, source: 'bridge' as const, ...this.advancedSearchForm.getRawValue(), }).subscribe() diff --git a/src-angular/app/core/services/search.service.ts b/src-angular/app/core/services/search.service.ts index 99467ae..d1f38d1 100644 --- a/src-angular/app/core/services/search.service.ts +++ b/src-angular/app/core/services/search.service.ts @@ -33,6 +33,8 @@ export class SearchService { public instrument: FormControl public difficulty: FormControl public drumType: FormControl + public sortDirection: 'asc' | 'desc' = 'asc' + public sortColumn: 'name' | 'artist' | 'album' | 'genre' | 'year' | 'charter' | 'length' | null = null constructor( private http: HttpClient, @@ -102,6 +104,7 @@ export class SearchService { instrument: this.instrument.value, difficulty: this.difficulty.value, drumType: this.drumType.value, + sort: this.sortColumn !== null ? { type: this.sortColumn, direction: this.sortDirection } : null, source: 'bridge', }).pipe( catchError((err, caught) => { @@ -212,4 +215,12 @@ export class SearchService { } } } + + public reloadSearch() { + if (this.isAdvancedSearch) { + this.advancedSearch(this.lastAdvancedSearch, false).subscribe() + } else { + this.search(this.searchControl.value || '*', false).subscribe() + } + } } diff --git a/src-shared/interfaces/search.interface.ts b/src-shared/interfaces/search.interface.ts index 80bcad9..00562b1 100644 --- a/src-shared/interfaces/search.interface.ts +++ b/src-shared/interfaces/search.interface.ts @@ -3,6 +3,7 @@ import { z } from 'zod' import { difficulties, drumTypeNames, instruments } from '../UtilFunctions.js' +export const searchSortProperties = ['name', 'artist', 'album', 'genre', 'year', 'charter', 'length', 'modifiedTime'] as const export const sources = ['website', 'bridge'] as const export const GeneralSearchSchema = z.object({ @@ -11,6 +12,10 @@ export const GeneralSearchSchema = z.object({ instrument: z.enum(instruments).nullable(), difficulty: z.enum(difficulties).nullable(), drumType: z.enum(drumTypeNames).nullable(), + sort: z + .object({ type: z.enum(searchSortProperties), direction: z.enum(['asc', 'desc']) }) + .nullable() + .default(null), source: z.enum(sources).optional(), }) export type GeneralSearch = z.infer @@ -27,6 +32,10 @@ export const AdvancedSearchSchema = z.object({ }, { message: 'Invalid instrument list' }).nullable(), difficulty: z.enum(difficulties).nullable(), drumType: z.enum(drumTypeNames).nullable(), + sort: z + .object({ type: z.enum(searchSortProperties), direction: z.enum(['asc', 'desc']) }) + .nullable() + .default(null), source: z.enum(sources).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() }), diff --git a/src-shared/search-api.ts b/src-shared/search-api.ts index 4062866..433ca1e 100644 --- a/src-shared/search-api.ts +++ b/src-shared/search-api.ts @@ -2,6 +2,7 @@ import { z } from 'zod' import { difficulties, drumTypeNames, instruments } from './UtilFunctions.js' +export const searchSortProperties = ['name', 'artist', 'album', 'genre', 'year', 'charter', 'length', 'modifiedTime'] as const export const sources = ['api'] as const export const GeneralSearchSchema = z.object({ @@ -11,6 +12,10 @@ export const GeneralSearchSchema = z.object({ instrument: z.enum(instruments).nullable().default(null), difficulty: z.enum(difficulties).nullable().default(null), drumType: z.enum(drumTypeNames).nullable().default(null), + sort: z + .object({ type: z.enum(searchSortProperties), direction: z.enum(['asc', 'desc']) }) + .nullable() + .default(null), source: z.enum(sources).optional(), }) export type GeneralSearch = z.infer @@ -22,6 +27,10 @@ export const AdvancedSearchSchema = z.object({ instrument: z.enum(instruments).nullable().default(null), difficulty: z.enum(difficulties).nullable().default(null), drumType: z.enum(drumTypeNames).nullable().default(null), + sort: z + .object({ type: z.enum(searchSortProperties), direction: z.enum(['asc', 'desc']) }) + .nullable() + .default(null), 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(),