diff --git a/frontend/src/Author/Details/BookRow.js b/frontend/src/Author/Details/BookRow.js
index 5eee601d2..717355363 100644
--- a/frontend/src/Author/Details/BookRow.js
+++ b/frontend/src/Author/Details/BookRow.js
@@ -71,7 +71,7 @@ class BookRow extends Component {
statistics,
releaseDate,
title,
- position,
+ seriesTitle,
pageCount,
ratings,
isSaving,
@@ -129,13 +129,13 @@ class BookRow extends Component {
);
}
- if (name === 'position') {
+ if (name === 'series') {
return (
- {position || ''}
+ {seriesTitle || ''}
);
}
@@ -215,7 +215,7 @@ BookRow.propTypes = {
monitored: PropTypes.bool.isRequired,
releaseDate: PropTypes.string,
title: PropTypes.string.isRequired,
- position: PropTypes.string,
+ seriesTitle: PropTypes.string.isRequired,
pageCount: PropTypes.number,
ratings: PropTypes.object.isRequired,
titleSlug: PropTypes.string.isRequired,
diff --git a/frontend/src/Book/Details/BookDetails.js b/frontend/src/Book/Details/BookDetails.js
index 97bb3b679..36dc53ca4 100644
--- a/frontend/src/Book/Details/BookDetails.js
+++ b/frontend/src/Book/Details/BookDetails.js
@@ -143,6 +143,7 @@ class BookDetails extends Component {
id,
titleSlug,
title,
+ seriesTitle,
pageCount,
overview,
statistics = {},
@@ -301,6 +302,10 @@ class BookDetails extends Component {
+
+ {seriesTitle}
+
+
{
!!pageCount &&
@@ -510,6 +515,7 @@ BookDetails.propTypes = {
id: PropTypes.number.isRequired,
titleSlug: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
+ seriesTitle: PropTypes.string.isRequired,
pageCount: PropTypes.number,
overview: PropTypes.string,
statistics: PropTypes.object.isRequired,
diff --git a/src/NzbDrone.Core/Books/Repositories/SeriesBookLinkRepository.cs b/src/NzbDrone.Core/Books/Repositories/SeriesBookLinkRepository.cs
index 142278c0b..9f9a9fb55 100644
--- a/src/NzbDrone.Core/Books/Repositories/SeriesBookLinkRepository.cs
+++ b/src/NzbDrone.Core/Books/Repositories/SeriesBookLinkRepository.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Linq;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events;
@@ -7,6 +8,7 @@ namespace NzbDrone.Core.Books
public interface ISeriesBookLinkRepository : IBasicRepository
{
List GetLinksBySeries(int seriesId);
+ List GetLinksByBook(List bookIds);
}
public class SeriesBookLinkRepository : BasicRepository, ISeriesBookLinkRepository
@@ -20,5 +22,19 @@ namespace NzbDrone.Core.Books
{
return Query(x => x.SeriesId == seriesId);
}
+
+ public List GetLinksByBook(List bookIds)
+ {
+ return _database.QueryJoined(
+ Builder()
+ .Join((l, s) => l.SeriesId == s.Id)
+ .Where(x => bookIds.Contains(x.BookId)),
+ (link, series) =>
+ {
+ link.Series = series;
+ return link;
+ })
+ .ToList();
+ }
}
}
diff --git a/src/NzbDrone.Core/Books/Services/SeriesBookLinkService.cs b/src/NzbDrone.Core/Books/Services/SeriesBookLinkService.cs
index c0f0585c9..f3c32c3b4 100644
--- a/src/NzbDrone.Core/Books/Services/SeriesBookLinkService.cs
+++ b/src/NzbDrone.Core/Books/Services/SeriesBookLinkService.cs
@@ -5,6 +5,7 @@ namespace NzbDrone.Core.Books
public interface ISeriesBookLinkService
{
List GetLinksBySeries(int seriesId);
+ List GetLinksByBook(List bookIds);
void InsertMany(List model);
void UpdateMany(List model);
void DeleteMany(List model);
@@ -24,6 +25,11 @@ namespace NzbDrone.Core.Books
return _repo.GetLinksBySeries(seriesId);
}
+ public List GetLinksByBook(List bookIds)
+ {
+ return _repo.GetLinksByBook(bookIds);
+ }
+
public void InsertMany(List model)
{
_repo.InsertMany(model);
diff --git a/src/Readarr.Api.V1/Books/BookModule.cs b/src/Readarr.Api.V1/Books/BookModule.cs
index b29f6dce4..3734abc6e 100644
--- a/src/Readarr.Api.V1/Books/BookModule.cs
+++ b/src/Readarr.Api.V1/Books/BookModule.cs
@@ -37,6 +37,7 @@ namespace Readarr.Api.V1.Books
IBookService bookService,
IAddBookService addBookService,
IEditionService editionService,
+ ISeriesBookLinkService seriesBookLinkService,
IAuthorStatisticsService authorStatisticsService,
IMapCoversToLocal coverMapper,
IUpgradableSpecification upgradableSpecification,
@@ -44,7 +45,7 @@ namespace Readarr.Api.V1.Books
QualityProfileExistsValidator qualityProfileExistsValidator,
MetadataProfileExistsValidator metadataProfileExistsValidator)
- : base(bookService, authorStatisticsService, coverMapper, upgradableSpecification, signalRBroadcaster)
+ : base(bookService, seriesBookLinkService, authorStatisticsService, coverMapper, upgradableSpecification, signalRBroadcaster)
{
_authorService = authorService;
_editionService = editionService;
diff --git a/src/Readarr.Api.V1/Books/BookModuleWithSignalR.cs b/src/Readarr.Api.V1/Books/BookModuleWithSignalR.cs
index 6cf516c87..bbca83628 100644
--- a/src/Readarr.Api.V1/Books/BookModuleWithSignalR.cs
+++ b/src/Readarr.Api.V1/Books/BookModuleWithSignalR.cs
@@ -14,18 +14,21 @@ namespace Readarr.Api.V1.Books
public abstract class BookModuleWithSignalR : ReadarrRestModuleWithSignalR
{
protected readonly IBookService _bookService;
+ protected readonly ISeriesBookLinkService _seriesBookLinkService;
protected readonly IAuthorStatisticsService _authorStatisticsService;
protected readonly IUpgradableSpecification _qualityUpgradableSpecification;
protected readonly IMapCoversToLocal _coverMapper;
protected BookModuleWithSignalR(IBookService bookService,
- IAuthorStatisticsService authorStatisticsService,
- IMapCoversToLocal coverMapper,
- IUpgradableSpecification qualityUpgradableSpecification,
- IBroadcastSignalRMessage signalRBroadcaster)
+ ISeriesBookLinkService seriesBookLinkService,
+ IAuthorStatisticsService authorStatisticsService,
+ IMapCoversToLocal coverMapper,
+ IUpgradableSpecification qualityUpgradableSpecification,
+ IBroadcastSignalRMessage signalRBroadcaster)
: base(signalRBroadcaster)
{
_bookService = bookService;
+ _seriesBookLinkService = seriesBookLinkService;
_authorStatisticsService = authorStatisticsService;
_coverMapper = coverMapper;
_qualityUpgradableSpecification = qualityUpgradableSpecification;
@@ -75,6 +78,22 @@ namespace Readarr.Api.V1.Books
protected List MapToResource(List books, bool includeAuthor)
{
+ var seriesLinks = _seriesBookLinkService.GetLinksByBook(books.Select(x => x.Id).ToList())
+ .GroupBy(x => x.BookId)
+ .ToDictionary(x => x.Key, y => y.ToList());
+
+ foreach (var book in books)
+ {
+ if (seriesLinks.TryGetValue(book.Id, out var links))
+ {
+ book.SeriesLinks = links;
+ }
+ else
+ {
+ book.SeriesLinks = new List();
+ }
+ }
+
var result = books.ToResource();
if (includeAuthor)
diff --git a/src/Readarr.Api.V1/Books/BookResource.cs b/src/Readarr.Api.V1/Books/BookResource.cs
index 55f18fbf3..2134eb691 100644
--- a/src/Readarr.Api.V1/Books/BookResource.cs
+++ b/src/Readarr.Api.V1/Books/BookResource.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
+using NzbDrone.Common.Extensions;
using NzbDrone.Core.Books;
using NzbDrone.Core.MediaCover;
using Readarr.Api.V1.Author;
@@ -13,6 +14,7 @@ namespace Readarr.Api.V1.Books
public class BookResource : RestResource
{
public string Title { get; set; }
+ public string SeriesTitle { get; set; }
public string Disambiguation { get; set; }
public string Overview { get; set; }
public int AuthorId { get; set; }
@@ -60,6 +62,7 @@ namespace Readarr.Api.V1.Books
PageCount = selectedEdition?.PageCount ?? 0,
Genres = model.Genres,
Title = selectedEdition?.Title ?? model.Title,
+ SeriesTitle = model.SeriesLinks.Value.Select(x => x.Series.Value.Title + (x.Position.IsNotNullOrWhiteSpace() ? $" #{x.Position}" : string.Empty)).ConcatToString("; "),
Disambiguation = selectedEdition?.Disambiguation,
Overview = selectedEdition?.Overview,
Images = selectedEdition?.Images ?? new List(),