Cleanup the search people API method

This commit is contained in:
Joseph Milazzo 2025-05-09 15:25:49 -05:00
parent a5c1c2e75f
commit 19d2e20f24
6 changed files with 22 additions and 17 deletions

View file

@ -48,10 +48,15 @@ public class PersonController : BaseApiController
return Ok(await _unitOfWork.PersonRepository.GetPersonDtoByName(name, User.GetUserId()));
}
[HttpGet("search-people")]
public async Task<ActionResult<List<PersonDto>>> SearchPeople([FromQuery] string name)
/// <summary>
/// Find a person by name or alias against a query string
/// </summary>
/// <param name="queryString"></param>
/// <returns></returns>
[HttpGet("search")]
public async Task<ActionResult<List<PersonDto>>> SearchPeople([FromQuery] string queryString)
{
var people = await _unitOfWork.PersonRepository.SearchPeople(name);
var people = await _unitOfWork.PersonRepository.SearchPeople(queryString);
return Ok(people.Select(person => _mapper.Map<PersonDto>(person)).ToList());
}

View file

@ -68,7 +68,7 @@ public interface IPersonRepository
Task<IList<Person>> GetPeopleByNames(List<string> normalizedNames, PersonIncludes includes = PersonIncludes.Aliases);
Task<Person?> GetPersonByAniListId(int aniListId, PersonIncludes includes = PersonIncludes.Aliases);
Task<IList<Person>> SearchPeople(string query, PersonIncludes includes = PersonIncludes.Aliases);
Task<IList<Person>> SearchPeople(string searchQuery, PersonIncludes includes = PersonIncludes.Aliases);
}
public class PersonRepository : IPersonRepository
@ -305,12 +305,14 @@ public class PersonRepository : IPersonRepository
.FirstOrDefaultAsync();
}
public async Task<IList<Person>> SearchPeople(string query, PersonIncludes includes = PersonIncludes.Aliases)
public async Task<IList<Person>> SearchPeople(string searchQuery, PersonIncludes includes = PersonIncludes.Aliases)
{
searchQuery = searchQuery.ToNormalized();
return await _context.Person
.Includes(includes)
.Where(p => EF.Functions.Like(p.Name, $"%{query}%")
|| p.Aliases.Any(pa => EF.Functions.Like(pa.Alias, $"%{query}%")))
.Where(p => EF.Functions.Like(p.Name, $"%{searchQuery}%")
|| p.Aliases.Any(pa => EF.Functions.Like(pa.Alias, $"%{searchQuery}%")))
.ToListAsync();
}

View file

@ -2,16 +2,13 @@ import { Injectable } from '@angular/core';
import {HttpClient, HttpParams} from "@angular/common/http";
import {environment} from "../../environments/environment";
import {Person, PersonRole} from "../_models/metadata/person";
import {SeriesFilterV2} from "../_models/metadata/v2/series-filter-v2";
import {PaginatedResult} from "../_models/pagination";
import {Series} from "../_models/series";
import {map} from "rxjs/operators";
import {UtilityService} from "../shared/_services/utility.service";
import {BrowsePerson} from "../_models/person/browse-person";
import {Chapter} from "../_models/chapter";
import {StandaloneChapter} from "../_models/standalone-chapter";
import {TextResonse} from "../_types/text-response";
import {al} from "@angular/router/router_module.d-6zbCxc1T";
@Injectable({
providedIn: 'root'
@ -31,7 +28,7 @@ export class PersonService {
}
searchPerson(name: string) {
return this.httpClient.get<Array<Person>>(this.baseUrl + `person/search-people?name=${name}`);
return this.httpClient.get<Array<Person>>(this.baseUrl + `person/search?queryString=${encodeURIComponent(name)}`);
}
getRolesForPerson(personId: number) {

View file

@ -5,7 +5,8 @@ import {
AsyncValidatorFn,
FormControl,
FormGroup,
ReactiveFormsModule, ValidationErrors,
ReactiveFormsModule,
ValidationErrors,
Validators
} from "@angular/forms";
import {Person} from "../../../_models/metadata/person";
@ -27,7 +28,6 @@ import {SettingItemComponent} from "../../../settings/_components/setting-item/s
import {AccountService} from "../../../_services/account.service";
import {ToastrService} from "ngx-toastr";
import {EditListComponent} from "../../../shared/edit-list/edit-list.component";
import {al} from "@angular/router/router_module.d-6zbCxc1T";
enum TabID {
General = 'general-tab',

View file

@ -73,6 +73,7 @@ export class MergePersonModalComponent implements OnInit {
}
this.typeAheadSettings.fetchFn = (filter: string) => {
if (filter.length == 0) return of([]);
return this.personService.searchPerson(filter).pipe(map(people => {
return people.filter(p => this.utilityService.filter(p.name, filter) && p.id != this.person.id);
}));

View file

@ -10,7 +10,7 @@ import {
} from '@angular/core';
import {ActivatedRoute, Router} from "@angular/router";
import {PersonService} from "../_services/person.service";
import {BehaviorSubject, EMPTY, Observable, of, switchMap, tap} from "rxjs";
import {BehaviorSubject, EMPTY, Observable, switchMap, tap} from "rxjs";
import {Person, PersonRole} from "../_models/metadata/person";
import {AsyncPipe} from "@angular/common";
import {ImageComponent} from "../shared/image/image.component";
@ -19,7 +19,7 @@ import {
SideNavCompanionBarComponent
} from "../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component";
import {ReadMoreComponent} from "../shared/read-more/read-more.component";
import {TagBadgeComponent, TagBadgeCursor} from "../shared/tag-badge/tag-badge.component";
import {TagBadgeCursor} from "../shared/tag-badge/tag-badge.component";
import {PersonRolePipe} from "../_pipes/person-role.pipe";
import {CarouselReelComponent} from "../carousel/_components/carousel-reel/carousel-reel.component";
import {FilterComparison} from "../_models/metadata/v2/filter-comparison";