Don't load all people for search, display series being merged in
This commit is contained in:
parent
940fe80609
commit
39b6382467
6 changed files with 44 additions and 8 deletions
|
|
@ -48,6 +48,13 @@ public class PersonController : BaseApiController
|
||||||
return Ok(await _unitOfWork.PersonRepository.GetPersonDtoByName(name, User.GetUserId()));
|
return Ok(await _unitOfWork.PersonRepository.GetPersonDtoByName(name, User.GetUserId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("search-people")]
|
||||||
|
public async Task<ActionResult<List<PersonDto>>> SearchPeople([FromQuery] string name)
|
||||||
|
{
|
||||||
|
var people = await _unitOfWork.PersonRepository.SearchPeople(name);
|
||||||
|
return Ok(people.Select(person => _mapper.Map<PersonDto>(person)).ToList());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns all roles for a Person
|
/// Returns all roles for a Person
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,8 @@ public interface IPersonRepository
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IList<Person>> GetPeopleByNames(List<string> normalizedNames, PersonIncludes includes = PersonIncludes.Aliases);
|
Task<IList<Person>> GetPeopleByNames(List<string> normalizedNames, PersonIncludes includes = PersonIncludes.Aliases);
|
||||||
Task<Person?> GetPersonByAniListId(int aniListId, PersonIncludes includes = PersonIncludes.Aliases);
|
Task<Person?> GetPersonByAniListId(int aniListId, PersonIncludes includes = PersonIncludes.Aliases);
|
||||||
|
|
||||||
|
Task<IList<Person>> SearchPeople(string query, PersonIncludes includes = PersonIncludes.Aliases);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PersonRepository : IPersonRepository
|
public class PersonRepository : IPersonRepository
|
||||||
|
|
@ -303,6 +305,15 @@ public class PersonRepository : IPersonRepository
|
||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IList<Person>> SearchPeople(string query, PersonIncludes includes = PersonIncludes.Aliases)
|
||||||
|
{
|
||||||
|
return await _context.Person
|
||||||
|
.Includes(includes)
|
||||||
|
.Where(p => EF.Functions.Like(p.Name, $"%{query}%")
|
||||||
|
|| p.Aliases.Any(pa => EF.Functions.Like(pa.Alias, $"%{query}%")))
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<IList<Person>> GetAllPeople(PersonIncludes includes = PersonIncludes.Aliases)
|
public async Task<IList<Person>> GetAllPeople(PersonIncludes includes = PersonIncludes.Aliases)
|
||||||
{
|
{
|
||||||
return await _context.Person
|
return await _context.Person
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ export class PersonService {
|
||||||
return this.httpClient.get<Person | null>(this.baseUrl + `person?name=${name}`);
|
return this.httpClient.get<Person | null>(this.baseUrl + `person?name=${name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getAliases(personId: number) {
|
searchPerson(name: string) {
|
||||||
return this.httpClient.get<Array<string>>(this.baseUrl + `person/aliases?personId=${personId}`);
|
return this.httpClient.get<Array<Person>>(this.baseUrl + `person/search-people?name=${name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRolesForPerson(personId: number) {
|
getRolesForPerson(personId: number) {
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,15 @@
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</app-badge-expander>
|
</app-badge-expander>
|
||||||
|
|
||||||
|
@if (knownFor$ | async; as knownFor) {
|
||||||
|
<h5 class="mt-2">{{t('known-for-title')}}</h5>
|
||||||
|
|
||||||
|
<app-badge-expander [items]="knownFor">
|
||||||
|
<ng-template #badgeExpanderItem let-item let-position="idx" let-last="last">
|
||||||
|
{{item.name}}
|
||||||
|
</ng-template>
|
||||||
|
</app-badge-expander>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import {Component, EventEmitter, inject, Input, OnInit} from '@angular/core';
|
import {Component, DestroyRef, EventEmitter, inject, Input, OnInit} from '@angular/core';
|
||||||
import {Person} from "../../../_models/metadata/person";
|
import {Person} from "../../../_models/metadata/person";
|
||||||
import {PersonService} from "../../../_services/person.service";
|
import {PersonService} from "../../../_services/person.service";
|
||||||
import {NgbActiveModal} from "@ng-bootstrap/ng-bootstrap";
|
import {NgbActiveModal} from "@ng-bootstrap/ng-bootstrap";
|
||||||
|
|
@ -8,10 +8,13 @@ import {TypeaheadComponent} from "../../../typeahead/_components/typeahead.compo
|
||||||
import {TypeaheadSettings} from "../../../typeahead/_models/typeahead-settings";
|
import {TypeaheadSettings} from "../../../typeahead/_models/typeahead-settings";
|
||||||
import {map} from "rxjs/operators";
|
import {map} from "rxjs/operators";
|
||||||
import {UtilityService} from "../../../shared/_services/utility.service";
|
import {UtilityService} from "../../../shared/_services/utility.service";
|
||||||
import {MetadataService} from "../../../_services/metadata.service";
|
|
||||||
import {SettingItemComponent} from "../../../settings/_components/setting-item/setting-item.component";
|
import {SettingItemComponent} from "../../../settings/_components/setting-item/setting-item.component";
|
||||||
import {BadgeExpanderComponent} from "../../../shared/badge-expander/badge-expander.component";
|
import {BadgeExpanderComponent} from "../../../shared/badge-expander/badge-expander.component";
|
||||||
import {FilterField} from "../../../_models/metadata/v2/filter-field";
|
import {FilterField} from "../../../_models/metadata/v2/filter-field";
|
||||||
|
import {Observable, of} from "rxjs";
|
||||||
|
import {Series} from "../../../_models/series";
|
||||||
|
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||||
|
import {AsyncPipe} from "@angular/common";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-merge-person-modal',
|
selector: 'app-merge-person-modal',
|
||||||
|
|
@ -19,7 +22,8 @@ import {FilterField} from "../../../_models/metadata/v2/filter-field";
|
||||||
TranslocoDirective,
|
TranslocoDirective,
|
||||||
TypeaheadComponent,
|
TypeaheadComponent,
|
||||||
SettingItemComponent,
|
SettingItemComponent,
|
||||||
BadgeExpanderComponent
|
BadgeExpanderComponent,
|
||||||
|
AsyncPipe
|
||||||
],
|
],
|
||||||
templateUrl: './merge-person-modal.component.html',
|
templateUrl: './merge-person-modal.component.html',
|
||||||
styleUrl: './merge-person-modal.component.scss'
|
styleUrl: './merge-person-modal.component.scss'
|
||||||
|
|
@ -28,7 +32,7 @@ export class MergePersonModalComponent implements OnInit {
|
||||||
|
|
||||||
private readonly personService = inject(PersonService);
|
private readonly personService = inject(PersonService);
|
||||||
public readonly utilityService = inject(UtilityService);
|
public readonly utilityService = inject(UtilityService);
|
||||||
private readonly metadataService = inject(MetadataService);
|
private readonly destroyRef = inject(DestroyRef);
|
||||||
private readonly modal = inject(NgbActiveModal);
|
private readonly modal = inject(NgbActiveModal);
|
||||||
protected readonly toastr = inject(ToastrService);
|
protected readonly toastr = inject(ToastrService);
|
||||||
|
|
||||||
|
|
@ -38,6 +42,7 @@ export class MergePersonModalComponent implements OnInit {
|
||||||
@Input({required: true}) person!: Person;
|
@Input({required: true}) person!: Person;
|
||||||
|
|
||||||
mergee: Person | null = null;
|
mergee: Person | null = null;
|
||||||
|
knownFor$: Observable<Series[]> | null = null;
|
||||||
|
|
||||||
save() {
|
save() {
|
||||||
if (!this.mergee) {
|
if (!this.mergee) {
|
||||||
|
|
@ -67,7 +72,8 @@ export class MergePersonModalComponent implements OnInit {
|
||||||
return a.name == b.name;
|
return a.name == b.name;
|
||||||
}
|
}
|
||||||
this.typeAheadSettings.fetchFn = (filter: string) => {
|
this.typeAheadSettings.fetchFn = (filter: string) => {
|
||||||
return this.metadataService.getAllPeople().pipe(map(people => {
|
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);
|
return people.filter(p => this.utilityService.filter(p.name, filter) && p.id != this.person.id);
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
@ -80,6 +86,8 @@ export class MergePersonModalComponent implements OnInit {
|
||||||
|
|
||||||
this.typeAheadUnfocus.emit(this.typeAheadSettings.id);
|
this.typeAheadUnfocus.emit(this.typeAheadSettings.id);
|
||||||
this.mergee = people[0];
|
this.mergee = people[0];
|
||||||
|
this.knownFor$ = this.personService.getSeriesMostKnownFor(this.mergee.id)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected readonly FilterField = FilterField;
|
protected readonly FilterField = FilterField;
|
||||||
|
|
|
||||||
|
|
@ -2278,7 +2278,8 @@
|
||||||
"save": "{{common.save}}",
|
"save": "{{common.save}}",
|
||||||
"src": "Merge Person",
|
"src": "Merge Person",
|
||||||
"merge-warning": "If you proceed, the selected person will be removed. If the target person has no existing names, the selected person's name will be added as their first name. Otherwise, the selected person's name will be added as an additional alias.",
|
"merge-warning": "If you proceed, the selected person will be removed. If the target person has no existing names, the selected person's name will be added as their first name. Otherwise, the selected person's name will be added as an additional alias.",
|
||||||
"alias-title": "New aliases"
|
"alias-title": "New aliases",
|
||||||
|
"known-for-title": "Known for"
|
||||||
},
|
},
|
||||||
|
|
||||||
"day-breakdown": {
|
"day-breakdown": {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue