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();
|
if (src == null) return BadRequest();
|
||||||
|
|
||||||
await _personService.MergePeopleAsync(dst, src);
|
await _personService.MergePeopleAsync(dst, src);
|
||||||
|
await _eventHub.SendMessageAsync(MessageFactory.PersonMerged, MessageFactory.PersonMergedMessage(dst, src));
|
||||||
|
|
||||||
return Ok(_mapper.Map<PersonDto>(dst));
|
return Ok(_mapper.Map<PersonDto>(dst));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,29 +65,8 @@ public class PersonService(IUnitOfWork unitOfWork): IPersonService
|
||||||
dst.CoverImage = src.CoverImage;
|
dst.CoverImage = src.CoverImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var chapter in src.ChapterPeople)
|
MergeChapterPeople(dst, src);
|
||||||
{
|
MergeSeriesMetadataPeople(dst, src);
|
||||||
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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
dst.Aliases.Add(new PersonAlias
|
dst.Aliases.Add(new PersonAlias
|
||||||
{
|
{
|
||||||
|
|
@ -105,6 +84,44 @@ public class PersonService(IUnitOfWork unitOfWork): IPersonService
|
||||||
await unitOfWork.CommitAsync();
|
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)
|
public async Task<bool> UpdatePersonAliasesAsync(Person person, IList<string> aliases)
|
||||||
{
|
{
|
||||||
var normalizedAliases = aliases
|
var normalizedAliases = aliases
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using API.DTOs.Update;
|
using API.DTOs.Update;
|
||||||
|
using API.Entities.Person;
|
||||||
using API.Extensions;
|
using API.Extensions;
|
||||||
using API.Services.Plus;
|
using API.Services.Plus;
|
||||||
|
|
||||||
|
|
@ -147,6 +148,10 @@ public static class MessageFactory
|
||||||
/// Volume is removed from server
|
/// Volume is removed from server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string VolumeRemoved = "VolumeRemoved";
|
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)
|
public static SignalRMessage DashboardUpdateEvent(int userId)
|
||||||
{
|
{
|
||||||
|
|
@ -661,4 +666,17 @@ public static class MessageFactory
|
||||||
EventType = ProgressEventType.Single,
|
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
|
* 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> {
|
export interface Message<T> {
|
||||||
|
|
@ -336,6 +340,13 @@ export class MessageHubService {
|
||||||
payload: resp.body
|
payload: resp.body
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.hubConnection.on(EVENTS.PersonMerged, resp => {
|
||||||
|
this.messagesSource.next({
|
||||||
|
event: EVENTS.PersonMerged,
|
||||||
|
payload: resp.body
|
||||||
|
});
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
stopHubConnection() {
|
stopHubConnection() {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import {
|
||||||
DestroyRef,
|
DestroyRef,
|
||||||
ElementRef,
|
ElementRef,
|
||||||
inject,
|
inject,
|
||||||
|
OnInit,
|
||||||
ViewChild
|
ViewChild
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import {ActivatedRoute, Router} from "@angular/router";
|
import {ActivatedRoute, Router} from "@angular/router";
|
||||||
|
|
@ -42,6 +43,14 @@ import {ToastrService} from "ngx-toastr";
|
||||||
import {LicenseService} from "../_services/license.service";
|
import {LicenseService} from "../_services/license.service";
|
||||||
import {SafeUrlPipe} from "../_pipes/safe-url.pipe";
|
import {SafeUrlPipe} from "../_pipes/safe-url.pipe";
|
||||||
import {MergePersonModalComponent} from "./_modal/merge-person-modal/merge-person-modal.component";
|
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({
|
@Component({
|
||||||
selector: 'app-person-detail',
|
selector: 'app-person-detail',
|
||||||
|
|
@ -63,7 +72,7 @@ import {MergePersonModalComponent} from "./_modal/merge-person-modal/merge-perso
|
||||||
styleUrl: './person-detail.component.scss',
|
styleUrl: './person-detail.component.scss',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class PersonDetailComponent {
|
export class PersonDetailComponent implements OnInit {
|
||||||
private readonly route = inject(ActivatedRoute);
|
private readonly route = inject(ActivatedRoute);
|
||||||
private readonly router = inject(Router);
|
private readonly router = inject(Router);
|
||||||
private readonly filterUtilityService = inject(FilterUtilitiesService);
|
private readonly filterUtilityService = inject(FilterUtilitiesService);
|
||||||
|
|
@ -77,6 +86,7 @@ export class PersonDetailComponent {
|
||||||
protected readonly licenseService = inject(LicenseService);
|
protected readonly licenseService = inject(LicenseService);
|
||||||
private readonly themeService = inject(ThemeService);
|
private readonly themeService = inject(ThemeService);
|
||||||
private readonly toastr = inject(ToastrService);
|
private readonly toastr = inject(ToastrService);
|
||||||
|
private readonly messageHubService = inject(MessageHubService)
|
||||||
|
|
||||||
protected readonly TagBadgeCursor = TagBadgeCursor;
|
protected readonly TagBadgeCursor = TagBadgeCursor;
|
||||||
|
|
||||||
|
|
@ -129,6 +139,17 @@ export class PersonDetailComponent {
|
||||||
).subscribe();
|
).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) {
|
private setPerson(person: Person) {
|
||||||
this.person = person;
|
this.person = person;
|
||||||
this.personSubject.next(person); // emit the person data for subscribers
|
this.personSubject.next(person); // emit the person data for subscribers
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue