Implemented Publication Status in SeriesMetadata and the ability to filter it. (#915)
This commit is contained in:
parent
f8e0fb8a27
commit
2fbcf203aa
28 changed files with 3015 additions and 19 deletions
|
@ -93,6 +93,27 @@ public class MetadataController : BaseApiController
|
|||
}));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches all publication status' from the instance
|
||||
/// </summary>
|
||||
/// <param name="libraryIds">String separated libraryIds or null for all publication status</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("publication-status")]
|
||||
public async Task<ActionResult<IList<AgeRatingDto>>> GetAllPublicationStatus(string? libraryIds)
|
||||
{
|
||||
var ids = libraryIds?.Split(",").Select(int.Parse).ToList();
|
||||
if (ids != null && ids.Count > 0)
|
||||
{
|
||||
return Ok(await _unitOfWork.SeriesRepository.GetAllPublicationStatusesDtosForLibrariesAsync(ids));
|
||||
}
|
||||
|
||||
return Ok(Enum.GetValues<PublicationStatus>().Select(t => new PublicationStatusDto()
|
||||
{
|
||||
Title = t.ToDescription(),
|
||||
Value = t
|
||||
}));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches all age ratings from the instance
|
||||
/// </summary>
|
||||
|
|
|
@ -53,7 +53,8 @@ public class OpdsController : BaseApiController
|
|||
CollectionTags = new List<int>(),
|
||||
CoverArtist = new List<int>(),
|
||||
ReadStatus = new ReadStatus(),
|
||||
SortOptions = null
|
||||
SortOptions = null,
|
||||
PublicationStatus = new List<PublicationStatus>()
|
||||
};
|
||||
private readonly ChapterSortComparer _chapterSortComparer = new ChapterSortComparer();
|
||||
|
||||
|
|
|
@ -70,6 +70,14 @@ namespace API.DTOs
|
|||
/// Language for the Chapter/Issue
|
||||
/// </summary>
|
||||
public string Language { get; set; }
|
||||
/// <summary>
|
||||
/// Number in the TotalCount of issues
|
||||
/// </summary>
|
||||
public int Count { get; set; }
|
||||
/// <summary>
|
||||
/// Total number of issues for the series
|
||||
/// </summary>
|
||||
public int TotalCount { get; set; }
|
||||
public ICollection<PersonDto> Writers { get; set; } = new List<PersonDto>();
|
||||
public ICollection<PersonDto> Penciller { get; set; } = new List<PersonDto>();
|
||||
public ICollection<PersonDto> Inker { get; set; } = new List<PersonDto>();
|
||||
|
|
|
@ -89,6 +89,10 @@ namespace API.DTOs.Filtering
|
|||
/// Languages (ISO 639-1 code) to filter by. Empty list will return everything back
|
||||
/// </summary>
|
||||
public IList<string> Languages { get; init; } = new List<string>();
|
||||
/// <summary>
|
||||
/// Publication statuses to filter by. Empty list will return everything back
|
||||
/// </summary>
|
||||
public IList<PublicationStatus> PublicationStatus { get; init; } = new List<PublicationStatus>();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
9
API/DTOs/Metadata/PublicationStatusDto.cs
Normal file
9
API/DTOs/Metadata/PublicationStatusDto.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
using API.Entities.Enums;
|
||||
|
||||
namespace API.DTOs.Metadata;
|
||||
|
||||
public class PublicationStatusDto
|
||||
{
|
||||
public PublicationStatus Value { get; set; }
|
||||
public string Title { get; set; }
|
||||
}
|
|
@ -43,6 +43,18 @@ namespace API.DTOs
|
|||
/// Language of the content (ISO 639-1 code)
|
||||
/// </summary>
|
||||
public string Language { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Number in the TotalCount of issues
|
||||
/// </summary>
|
||||
public int Count { get; set; }
|
||||
/// <summary>
|
||||
/// Total number of issues for the series
|
||||
/// </summary>
|
||||
public int TotalCount { get; set; }
|
||||
/// <summary>
|
||||
/// Publication status of the Series
|
||||
/// </summary>
|
||||
public PublicationStatus PublicationStatus { get; set; }
|
||||
|
||||
public int SeriesId { get; set; }
|
||||
}
|
||||
|
|
|
@ -8,13 +8,17 @@ namespace API.Data.Metadata
|
|||
/// <summary>
|
||||
/// A representation of a ComicInfo.xml file
|
||||
/// </summary>
|
||||
/// <remarks>See reference of the loose spec here: https://github.com/Kussie/ComicInfoStandard/blob/main/ComicInfo.xsd</remarks>
|
||||
/// <remarks>See reference of the loose spec here: https://anansi-project.github.io/docs/comicinfo/documentation</remarks>
|
||||
public class ComicInfo
|
||||
{
|
||||
public string Summary { get; set; } = string.Empty;
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public string Series { get; set; } = string.Empty;
|
||||
public string Number { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// The total number of items in the series.
|
||||
/// </summary>
|
||||
public int Count { get; set; } = 0;
|
||||
public string Volume { get; set; } = string.Empty;
|
||||
public string Notes { get; set; } = string.Empty;
|
||||
public string Genre { get; set; } = string.Empty;
|
||||
|
|
1345
API/Data/Migrations/20220108200822_CountMetadata.Designer.cs
generated
Normal file
1345
API/Data/Migrations/20220108200822_CountMetadata.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
37
API/Data/Migrations/20220108200822_CountMetadata.cs
Normal file
37
API/Data/Migrations/20220108200822_CountMetadata.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace API.Data.Migrations
|
||||
{
|
||||
public partial class CountMetadata : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Count",
|
||||
table: "SeriesMetadata",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Count",
|
||||
table: "Chapter",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Count",
|
||||
table: "SeriesMetadata");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Count",
|
||||
table: "Chapter");
|
||||
}
|
||||
}
|
||||
}
|
1351
API/Data/Migrations/20220108202027_PublicationStatus.Designer.cs
generated
Normal file
1351
API/Data/Migrations/20220108202027_PublicationStatus.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
37
API/Data/Migrations/20220108202027_PublicationStatus.cs
Normal file
37
API/Data/Migrations/20220108202027_PublicationStatus.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace API.Data.Migrations
|
||||
{
|
||||
public partial class PublicationStatus : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "PublicationStatus",
|
||||
table: "SeriesMetadata",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "TotalCount",
|
||||
table: "Chapter",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PublicationStatus",
|
||||
table: "SeriesMetadata");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TotalCount",
|
||||
table: "Chapter");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -299,6 +299,9 @@ namespace API.Data.Migrations
|
|||
b.Property<int>("AgeRating")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("CoverImage")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
|
@ -338,6 +341,9 @@ namespace API.Data.Migrations
|
|||
b.Property<string>("TitleName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("TotalCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("VolumeId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
|
@ -494,9 +500,15 @@ namespace API.Data.Migrations
|
|||
b.Property<int>("AgeRating")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Language")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("PublicationStatus")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ReleaseYear")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ public interface ISeriesRepository
|
|||
Task<IList<SeriesMetadata>> GetSeriesMetadataForIdsAsync(IEnumerable<int> seriesIds);
|
||||
Task<IList<AgeRatingDto>> GetAllAgeRatingsDtosForLibrariesAsync(List<int> libraryIds);
|
||||
Task<IList<LanguageDto>> GetAllLanguagesForLibrariesAsync(List<int> libraryIds);
|
||||
Task<IList<PublicationStatusDto>> GetAllPublicationStatusesDtosForLibrariesAsync(List<int> libraryIds);
|
||||
}
|
||||
|
||||
public class SeriesRepository : ISeriesRepository
|
||||
|
@ -425,7 +426,7 @@ public class SeriesRepository : ISeriesRepository
|
|||
private IList<MangaFormat> ExtractFilters(int libraryId, int userId, FilterDto filter, ref List<int> userLibraries,
|
||||
out List<int> allPeopleIds, out bool hasPeopleFilter, out bool hasGenresFilter, out bool hasCollectionTagFilter,
|
||||
out bool hasRatingFilter, out bool hasProgressFilter, out IList<int> seriesIds, out bool hasAgeRating, out bool hasTagsFilter,
|
||||
out bool hasLanguageFilter)
|
||||
out bool hasLanguageFilter, out bool hasPublicationFilter)
|
||||
{
|
||||
var formats = filter.GetSqlFilter();
|
||||
|
||||
|
@ -454,6 +455,7 @@ public class SeriesRepository : ISeriesRepository
|
|||
hasAgeRating = filter.AgeRating.Count > 0;
|
||||
hasTagsFilter = filter.Tags.Count > 0;
|
||||
hasLanguageFilter = filter.Languages.Count > 0;
|
||||
hasPublicationFilter = filter.PublicationStatus.Count > 0;
|
||||
|
||||
|
||||
bool ProgressComparison(int pagesRead, int totalPages)
|
||||
|
@ -541,7 +543,7 @@ public class SeriesRepository : ISeriesRepository
|
|||
var formats = ExtractFilters(libraryId, userId, filter, ref userLibraries,
|
||||
out var allPeopleIds, out var hasPeopleFilter, out var hasGenresFilter,
|
||||
out var hasCollectionTagFilter, out var hasRatingFilter, out var hasProgressFilter,
|
||||
out var seriesIds, out var hasAgeRating, out var hasTagsFilter, out var hasLanguageFilter);
|
||||
out var seriesIds, out var hasAgeRating, out var hasTagsFilter, out var hasLanguageFilter, out var hasPublicationFilter);
|
||||
|
||||
var query = _context.Series
|
||||
.Where(s => userLibraries.Contains(s.LibraryId)
|
||||
|
@ -555,6 +557,7 @@ public class SeriesRepository : ISeriesRepository
|
|||
&& (!hasAgeRating || filter.AgeRating.Contains(s.Metadata.AgeRating))
|
||||
&& (!hasTagsFilter || s.Metadata.Tags.Any(t => filter.Tags.Contains(t.Id)))
|
||||
&& (!hasLanguageFilter || filter.Languages.Contains(s.Metadata.Language))
|
||||
&& (!hasPublicationFilter || filter.PublicationStatus.Contains(s.Metadata.PublicationStatus))
|
||||
)
|
||||
.AsNoTracking();
|
||||
|
||||
|
@ -769,4 +772,18 @@ public class SeriesRepository : ISeriesRepository
|
|||
IsoCode = s
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public async Task<IList<PublicationStatusDto>> GetAllPublicationStatusesDtosForLibrariesAsync(List<int> libraryIds)
|
||||
{
|
||||
return await _context.Series
|
||||
.Where(s => libraryIds.Contains(s.LibraryId))
|
||||
.Select(s => s.Metadata.PublicationStatus)
|
||||
.Distinct()
|
||||
.Select(s => new PublicationStatusDto()
|
||||
{
|
||||
Value = s,
|
||||
Title = s.ToDescription()
|
||||
})
|
||||
.ToListAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,14 @@ namespace API.Entities
|
|||
/// Language for the Chapter/Issue
|
||||
/// </summary>
|
||||
public string Language { get; set; }
|
||||
/// <summary>
|
||||
/// Total number of issues in the series
|
||||
/// </summary>
|
||||
public int TotalCount { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// Number in the Total Count
|
||||
/// </summary>
|
||||
public int Count { get; set; } = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
|
23
API/Entities/Enums/PublicationStatus.cs
Normal file
23
API/Entities/Enums/PublicationStatus.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
using System.ComponentModel;
|
||||
|
||||
namespace API.Entities.Enums;
|
||||
|
||||
public enum PublicationStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Default Status. Publication is currently in progress
|
||||
/// </summary>
|
||||
[Description("On Going")]
|
||||
OnGoing = 0,
|
||||
/// <summary>
|
||||
/// Series is on temp or indefinite Hiatus
|
||||
/// </summary>
|
||||
[Description("Hiatus")]
|
||||
Hiatus = 1,
|
||||
/// <summary>
|
||||
/// Publication has finished releasing
|
||||
/// </summary>
|
||||
[Description("Completed")]
|
||||
Completed = 2
|
||||
|
||||
}
|
|
@ -14,7 +14,6 @@ namespace API.Entities.Metadata
|
|||
|
||||
public string Summary { get; set; }
|
||||
|
||||
|
||||
public ICollection<CollectionTag> CollectionTags { get; set; }
|
||||
|
||||
public ICollection<Genre> Genres { get; set; } = new List<Genre>();
|
||||
|
@ -36,6 +35,11 @@ namespace API.Entities.Metadata
|
|||
/// Language of the content (ISO 639-1 code)
|
||||
/// </summary>
|
||||
public string Language { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Total number of issues in the series
|
||||
/// </summary>
|
||||
public int Count { get; set; } = 0;
|
||||
public PublicationStatus PublicationStatus { get; set; }
|
||||
|
||||
// Relationship
|
||||
public Series Series { get; set; }
|
||||
|
|
|
@ -107,6 +107,19 @@ public class MetadataService : IMetadataService
|
|||
chapter.Language = comicInfo.LanguageISO;
|
||||
}
|
||||
|
||||
if (comicInfo.Count > 0)
|
||||
{
|
||||
chapter.TotalCount = comicInfo.Count;
|
||||
}
|
||||
|
||||
if (int.Parse(comicInfo.Number) > 0)
|
||||
{
|
||||
chapter.Count = int.Parse(comicInfo.Number);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (comicInfo.Year > 0)
|
||||
{
|
||||
var day = Math.Max(comicInfo.Day, 1);
|
||||
|
@ -295,6 +308,13 @@ public class MetadataService : IMetadataService
|
|||
series.Metadata.AgeRating = chapters.Max(chapter => chapter.AgeRating);
|
||||
|
||||
|
||||
series.Metadata.Count = chapters.Max(chapter => chapter.TotalCount);
|
||||
series.Metadata.PublicationStatus = PublicationStatus.OnGoing;
|
||||
if (chapters.Max(chapter => chapter.Count) >= series.Metadata.Count)
|
||||
{
|
||||
series.Metadata.PublicationStatus = PublicationStatus.Completed;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(firstChapter.Summary))
|
||||
{
|
||||
series.Metadata.Summary = firstChapter.Summary;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue