Don't add ChapterPeople / SeriesMetataPeople if already present for that role and series
Redirects on merge for users currently on that page
This commit is contained in:
parent
6ec7e80a43
commit
95dc321bf9
5 changed files with 94 additions and 25 deletions
|
|
@ -196,6 +196,8 @@ public class PersonController : BaseApiController
|
|||
if (src == null) return BadRequest();
|
||||
|
||||
await _personService.MergePeopleAsync(dst, src);
|
||||
await _eventHub.SendMessageAsync(MessageFactory.PersonMerged, MessageFactory.PersonMergedMessage(dst, src));
|
||||
|
||||
return Ok(_mapper.Map<PersonDto>(dst));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,29 +65,8 @@ public class PersonService(IUnitOfWork unitOfWork): IPersonService
|
|||
dst.CoverImage = src.CoverImage;
|
||||
}
|
||||
|
||||
foreach (var chapter in src.ChapterPeople)
|
||||
{
|
||||
dst.ChapterPeople.Add(new ChapterPeople
|
||||
{
|
||||
Role = chapter.Role,
|
||||
ChapterId = chapter.ChapterId,
|
||||
Person = dst,
|
||||
KavitaPlusConnection = chapter.KavitaPlusConnection,
|
||||
OrderWeight = chapter.OrderWeight,
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var series in src.SeriesMetadataPeople)
|
||||
{
|
||||
dst.SeriesMetadataPeople.Add(new SeriesMetadataPeople
|
||||
{
|
||||
SeriesMetadataId = series.SeriesMetadataId,
|
||||
Role = series.Role,
|
||||
Person = dst,
|
||||
KavitaPlusConnection = series.KavitaPlusConnection,
|
||||
OrderWeight = series.OrderWeight,
|
||||
});
|
||||
}
|
||||
MergeChapterPeople(dst, src);
|
||||
MergeSeriesMetadataPeople(dst, src);
|
||||
|
||||
dst.Aliases.Add(new PersonAlias
|
||||
{
|
||||
|
|
@ -105,6 +84,44 @@ public class PersonService(IUnitOfWork unitOfWork): IPersonService
|
|||
await unitOfWork.CommitAsync();
|
||||
}
|
||||
|
||||
private void MergeChapterPeople(Person dst, Person src)
|
||||
{
|
||||
foreach (var chapter in src.ChapterPeople)
|
||||
{
|
||||
var alreadyPresent = dst.ChapterPeople
|
||||
.Any(x => x.ChapterId == chapter.ChapterId && x.Role == chapter.Role);
|
||||
if (alreadyPresent) continue;
|
||||
|
||||
dst.ChapterPeople.Add(new ChapterPeople
|
||||
{
|
||||
Role = chapter.Role,
|
||||
ChapterId = chapter.ChapterId,
|
||||
Person = dst,
|
||||
KavitaPlusConnection = chapter.KavitaPlusConnection,
|
||||
OrderWeight = chapter.OrderWeight,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void MergeSeriesMetadataPeople(Person dst, Person src)
|
||||
{
|
||||
foreach (var series in src.SeriesMetadataPeople)
|
||||
{
|
||||
var alreadyPresent = dst.SeriesMetadataPeople
|
||||
.Any(x => x.SeriesMetadataId == series.SeriesMetadataId && x.Role == series.Role);
|
||||
if (alreadyPresent) continue;
|
||||
|
||||
dst.SeriesMetadataPeople.Add(new SeriesMetadataPeople
|
||||
{
|
||||
SeriesMetadataId = series.SeriesMetadataId,
|
||||
Role = series.Role,
|
||||
Person = dst,
|
||||
KavitaPlusConnection = series.KavitaPlusConnection,
|
||||
OrderWeight = series.OrderWeight,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdatePersonAliasesAsync(Person person, IList<string> aliases)
|
||||
{
|
||||
var normalizedAliases = aliases
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using API.DTOs.Update;
|
||||
using API.Entities.Person;
|
||||
using API.Extensions;
|
||||
using API.Services.Plus;
|
||||
|
||||
|
|
@ -147,6 +148,10 @@ public static class MessageFactory
|
|||
/// Volume is removed from server
|
||||
/// </summary>
|
||||
public const string VolumeRemoved = "VolumeRemoved";
|
||||
/// <summary>
|
||||
/// A Person merged has been merged into another
|
||||
/// </summary>
|
||||
public const string PersonMerged = "PersonMerged";
|
||||
|
||||
public static SignalRMessage DashboardUpdateEvent(int userId)
|
||||
{
|
||||
|
|
@ -661,4 +666,17 @@ public static class MessageFactory
|
|||
EventType = ProgressEventType.Single,
|
||||
};
|
||||
}
|
||||
|
||||
public static SignalRMessage PersonMergedMessage(Person dst, Person src)
|
||||
{
|
||||
return new SignalRMessage()
|
||||
{
|
||||
Name = PersonMerged,
|
||||
Body = new
|
||||
{
|
||||
srcId = src.Id,
|
||||
dstName = dst.Name,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,11 @@ export enum EVENTS {
|
|||
/**
|
||||
* A Progress event when a smart collection is synchronizing
|
||||
*/
|
||||
SmartCollectionSync = 'SmartCollectionSync'
|
||||
SmartCollectionSync = 'SmartCollectionSync',
|
||||
/**
|
||||
* A Person merged has been merged into another
|
||||
*/
|
||||
PersonMerged = 'PersonMerged',
|
||||
}
|
||||
|
||||
export interface Message<T> {
|
||||
|
|
@ -336,6 +340,13 @@ export class MessageHubService {
|
|||
payload: resp.body
|
||||
});
|
||||
});
|
||||
|
||||
this.hubConnection.on(EVENTS.PersonMerged, resp => {
|
||||
this.messagesSource.next({
|
||||
event: EVENTS.PersonMerged,
|
||||
payload: resp.body
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
stopHubConnection() {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import {
|
|||
DestroyRef,
|
||||
ElementRef,
|
||||
inject,
|
||||
OnInit,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
|
|
@ -42,6 +43,14 @@ import {ToastrService} from "ngx-toastr";
|
|||
import {LicenseService} from "../_services/license.service";
|
||||
import {SafeUrlPipe} from "../_pipes/safe-url.pipe";
|
||||
import {MergePersonModalComponent} from "./_modal/merge-person-modal/merge-person-modal.component";
|
||||
import {EVENTS, MessageHubService} from "../_services/message-hub.service";
|
||||
|
||||
interface PersonMergeEvent {
|
||||
srcId: number,
|
||||
dstId: number,
|
||||
dstName: number,
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-person-detail',
|
||||
|
|
@ -63,7 +72,7 @@ import {MergePersonModalComponent} from "./_modal/merge-person-modal/merge-perso
|
|||
styleUrl: './person-detail.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class PersonDetailComponent {
|
||||
export class PersonDetailComponent implements OnInit {
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
private readonly router = inject(Router);
|
||||
private readonly filterUtilityService = inject(FilterUtilitiesService);
|
||||
|
|
@ -77,6 +86,7 @@ export class PersonDetailComponent {
|
|||
protected readonly licenseService = inject(LicenseService);
|
||||
private readonly themeService = inject(ThemeService);
|
||||
private readonly toastr = inject(ToastrService);
|
||||
private readonly messageHubService = inject(MessageHubService)
|
||||
|
||||
protected readonly TagBadgeCursor = TagBadgeCursor;
|
||||
|
||||
|
|
@ -129,6 +139,17 @@ export class PersonDetailComponent {
|
|||
).subscribe();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.messageHubService.messages$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(message => {
|
||||
if (message.event !== EVENTS.PersonMerged) return;
|
||||
|
||||
const event = message.payload as PersonMergeEvent;
|
||||
if (event.srcId !== this.person?.id) return;
|
||||
|
||||
this.router.navigate(['person', event.dstName]);
|
||||
});
|
||||
}
|
||||
|
||||
private setPerson(person: Person) {
|
||||
this.person = person;
|
||||
this.personSubject.next(person); // emit the person data for subscribers
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue