From da99c978134a5cb91496c101e44ed2e5bf79dc6d Mon Sep 17 00:00:00 2001 From: Joseph Milazzo Date: Tue, 29 Apr 2025 10:05:01 -0500 Subject: [PATCH] Hooked up average rating for the issue, external ratings for individual issues (cbr only), and some polish. Show Issues not Chapters for CBR matches. --- API/Controllers/ChapterController.cs | 2 + API/DTOs/ChapterDetailPlusDto.cs | 4 +- API/DTOs/SeriesDetail/UserReviewDto.cs | 3 + ...50140_ChapterRatingAndReviews.Designer.cs} | 24 +++++++- ...20250429150140_ChapterRatingAndReviews.cs} | 54 +++++++++++++++++- .../Migrations/DataContextModelSnapshot.cs | 20 +++++++ API/Data/Repositories/ChapterRepository.cs | 10 ++++ API/Entities/Chapter.cs | 8 ++- API/Entities/Enums/RatingAuthority.cs | 10 ++++ API/Entities/Metadata/ExternalRating.cs | 6 ++ API/Services/Plus/ExternalMetadataService.cs | 57 ++++++++++++++++--- UI/Web/src/app/_models/rating.ts | 6 ++ .../match-series-result-item.component.html | 6 +- .../match-series-result-item.component.ts | 2 + .../_single-module/review-card/user-review.ts | 5 +- .../chapter-detail.component.html | 2 +- .../chapter-detail.component.ts | 28 ++++----- .../external-rating.component.html | 3 +- .../external-rating.component.ts | 16 ++++-- .../series-detail.component.html | 1 - UI/Web/src/assets/langs/en.json | 4 +- 21 files changed, 231 insertions(+), 40 deletions(-) rename API/Data/Migrations/{20250428180534_ChapterRating.Designer.cs => 20250429150140_ChapterRatingAndReviews.Designer.cs} (99%) rename API/Data/Migrations/{20250428180534_ChapterRating.cs => 20250429150140_ChapterRatingAndReviews.cs} (70%) diff --git a/API/Controllers/ChapterController.cs b/API/Controllers/ChapterController.cs index 835102914..596731345 100644 --- a/API/Controllers/ChapterController.cs +++ b/API/Controllers/ChapterController.cs @@ -423,6 +423,8 @@ public class ChapterController : BaseApiController ret.Reviews = userReviews; + ret.Ratings = await _unitOfWork.ChapterRepository.GetExternalChapterRatings(chapterId); + return ret; } diff --git a/API/DTOs/ChapterDetailPlusDto.cs b/API/DTOs/ChapterDetailPlusDto.cs index 24649edaa..9f9cfb8ab 100644 --- a/API/DTOs/ChapterDetailPlusDto.cs +++ b/API/DTOs/ChapterDetailPlusDto.cs @@ -9,6 +9,6 @@ public class ChapterDetailPlusDto public float Rating { get; set; } public bool HasBeenRated { get; set; } - public List Reviews { get; set; } - public List? Ratings { get; set; } + public IList Reviews { get; set; } = []; + public IList Ratings { get; set; } = []; } diff --git a/API/DTOs/SeriesDetail/UserReviewDto.cs b/API/DTOs/SeriesDetail/UserReviewDto.cs index d21afdd15..c8340a40a 100644 --- a/API/DTOs/SeriesDetail/UserReviewDto.cs +++ b/API/DTOs/SeriesDetail/UserReviewDto.cs @@ -57,5 +57,8 @@ public class UserReviewDto /// If this review is External, which Provider did it come from /// public ScrobbleProvider Provider { get; set; } = ScrobbleProvider.Kavita; + /// + /// Source of the Rating + /// public RatingAuthority Authority { get; set; } = RatingAuthority.User; } diff --git a/API/Data/Migrations/20250428180534_ChapterRating.Designer.cs b/API/Data/Migrations/20250429150140_ChapterRatingAndReviews.Designer.cs similarity index 99% rename from API/Data/Migrations/20250428180534_ChapterRating.Designer.cs rename to API/Data/Migrations/20250429150140_ChapterRatingAndReviews.Designer.cs index 8eb9c1fda..52e2c4a86 100644 --- a/API/Data/Migrations/20250428180534_ChapterRating.Designer.cs +++ b/API/Data/Migrations/20250429150140_ChapterRatingAndReviews.Designer.cs @@ -11,8 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace API.Data.Migrations { [DbContext(typeof(DataContext))] - [Migration("20250428180534_ChapterRating")] - partial class ChapterRating + [Migration("20250429150140_ChapterRatingAndReviews")] + partial class ChapterRatingAndReviews { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -790,6 +790,9 @@ namespace API.Data.Migrations b.Property("AlternateSeries") .HasColumnType("TEXT"); + b.Property("AverageExternalRating") + .HasColumnType("REAL"); + b.Property("AvgHoursToRead") .HasColumnType("REAL"); @@ -1354,9 +1357,15 @@ namespace API.Data.Migrations .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); + b.Property("Authority") + .HasColumnType("INTEGER"); + b.Property("AverageScore") .HasColumnType("INTEGER"); + b.Property("ChapterId") + .HasColumnType("INTEGER"); + b.Property("FavoriteCount") .HasColumnType("INTEGER"); @@ -1371,6 +1380,8 @@ namespace API.Data.Migrations b.HasKey("Id"); + b.HasIndex("ChapterId"); + b.ToTable("ExternalRating"); }); @@ -2978,6 +2989,13 @@ namespace API.Data.Migrations b.Navigation("Chapter"); }); + modelBuilder.Entity("API.Entities.Metadata.ExternalRating", b => + { + b.HasOne("API.Entities.Chapter", null) + .WithMany("ExternalRatings") + .HasForeignKey("ChapterId"); + }); + modelBuilder.Entity("API.Entities.Metadata.ExternalReview", b => { b.HasOne("API.Entities.Chapter", null) @@ -3445,6 +3463,8 @@ namespace API.Data.Migrations modelBuilder.Entity("API.Entities.Chapter", b => { + b.Navigation("ExternalRatings"); + b.Navigation("ExternalReviews"); b.Navigation("Files"); diff --git a/API/Data/Migrations/20250428180534_ChapterRating.cs b/API/Data/Migrations/20250429150140_ChapterRatingAndReviews.cs similarity index 70% rename from API/Data/Migrations/20250428180534_ChapterRating.cs rename to API/Data/Migrations/20250429150140_ChapterRatingAndReviews.cs index a75d5c24b..5ab51aaba 100644 --- a/API/Data/Migrations/20250428180534_ChapterRating.cs +++ b/API/Data/Migrations/20250429150140_ChapterRatingAndReviews.cs @@ -5,7 +5,7 @@ namespace API.Data.Migrations { /// - public partial class ChapterRating : Migration + public partial class ChapterRatingAndReviews : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -23,6 +23,26 @@ namespace API.Data.Migrations type: "INTEGER", nullable: true); + migrationBuilder.AddColumn( + name: "Authority", + table: "ExternalRating", + type: "INTEGER", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "ChapterId", + table: "ExternalRating", + type: "INTEGER", + nullable: true); + + migrationBuilder.AddColumn( + name: "AverageExternalRating", + table: "Chapter", + type: "REAL", + nullable: false, + defaultValue: 0f); + migrationBuilder.CreateTable( name: "AppUserChapterRating", columns: table => new @@ -64,6 +84,11 @@ namespace API.Data.Migrations table: "ExternalReview", column: "ChapterId"); + migrationBuilder.CreateIndex( + name: "IX_ExternalRating_ChapterId", + table: "ExternalRating", + column: "ChapterId"); + migrationBuilder.CreateIndex( name: "IX_AppUserChapterRating_AppUserId", table: "AppUserChapterRating", @@ -79,6 +104,13 @@ namespace API.Data.Migrations table: "AppUserChapterRating", column: "SeriesId"); + migrationBuilder.AddForeignKey( + name: "FK_ExternalRating_Chapter_ChapterId", + table: "ExternalRating", + column: "ChapterId", + principalTable: "Chapter", + principalColumn: "Id"); + migrationBuilder.AddForeignKey( name: "FK_ExternalReview_Chapter_ChapterId", table: "ExternalReview", @@ -90,6 +122,10 @@ namespace API.Data.Migrations /// protected override void Down(MigrationBuilder migrationBuilder) { + migrationBuilder.DropForeignKey( + name: "FK_ExternalRating_Chapter_ChapterId", + table: "ExternalRating"); + migrationBuilder.DropForeignKey( name: "FK_ExternalReview_Chapter_ChapterId", table: "ExternalReview"); @@ -101,6 +137,10 @@ namespace API.Data.Migrations name: "IX_ExternalReview_ChapterId", table: "ExternalReview"); + migrationBuilder.DropIndex( + name: "IX_ExternalRating_ChapterId", + table: "ExternalRating"); + migrationBuilder.DropColumn( name: "Authority", table: "ExternalReview"); @@ -108,6 +148,18 @@ namespace API.Data.Migrations migrationBuilder.DropColumn( name: "ChapterId", table: "ExternalReview"); + + migrationBuilder.DropColumn( + name: "Authority", + table: "ExternalRating"); + + migrationBuilder.DropColumn( + name: "ChapterId", + table: "ExternalRating"); + + migrationBuilder.DropColumn( + name: "AverageExternalRating", + table: "Chapter"); } } } diff --git a/API/Data/Migrations/DataContextModelSnapshot.cs b/API/Data/Migrations/DataContextModelSnapshot.cs index 46dabef6a..a66568dcc 100644 --- a/API/Data/Migrations/DataContextModelSnapshot.cs +++ b/API/Data/Migrations/DataContextModelSnapshot.cs @@ -787,6 +787,9 @@ namespace API.Data.Migrations b.Property("AlternateSeries") .HasColumnType("TEXT"); + b.Property("AverageExternalRating") + .HasColumnType("REAL"); + b.Property("AvgHoursToRead") .HasColumnType("REAL"); @@ -1351,9 +1354,15 @@ namespace API.Data.Migrations .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); + b.Property("Authority") + .HasColumnType("INTEGER"); + b.Property("AverageScore") .HasColumnType("INTEGER"); + b.Property("ChapterId") + .HasColumnType("INTEGER"); + b.Property("FavoriteCount") .HasColumnType("INTEGER"); @@ -1368,6 +1377,8 @@ namespace API.Data.Migrations b.HasKey("Id"); + b.HasIndex("ChapterId"); + b.ToTable("ExternalRating"); }); @@ -2975,6 +2986,13 @@ namespace API.Data.Migrations b.Navigation("Chapter"); }); + modelBuilder.Entity("API.Entities.Metadata.ExternalRating", b => + { + b.HasOne("API.Entities.Chapter", null) + .WithMany("ExternalRatings") + .HasForeignKey("ChapterId"); + }); + modelBuilder.Entity("API.Entities.Metadata.ExternalReview", b => { b.HasOne("API.Entities.Chapter", null) @@ -3442,6 +3460,8 @@ namespace API.Data.Migrations modelBuilder.Entity("API.Entities.Chapter", b => { + b.Navigation("ExternalRatings"); + b.Navigation("ExternalReviews"); b.Navigation("Files"); diff --git a/API/Data/Repositories/ChapterRepository.cs b/API/Data/Repositories/ChapterRepository.cs index 5a73f3bed..650b9ac93 100644 --- a/API/Data/Repositories/ChapterRepository.cs +++ b/API/Data/Repositories/ChapterRepository.cs @@ -52,6 +52,7 @@ public interface IChapterRepository Task> GetAllChaptersForSeries(int seriesId); Task GetAverageUserRating(int chapterId, int userId); Task> GetExternalChapterReviews(int chapterId); + Task> GetExternalChapterRatings(int chapterId); } public class ChapterRepository : IChapterRepository { @@ -340,4 +341,13 @@ public class ChapterRepository : IChapterRepository .Select(r => _mapper.Map(r)) .ToListAsync(); } + + public async Task> GetExternalChapterRatings(int chapterId) + { + return await _context.Chapter + .Where(c => c.Id == chapterId) + .SelectMany(c => c.ExternalRatings) + .ProjectTo(_mapper.ConfigurationProvider) + .ToListAsync(); + } } diff --git a/API/Entities/Chapter.cs b/API/Entities/Chapter.cs index 5d2608557..61a70c8a2 100644 --- a/API/Entities/Chapter.cs +++ b/API/Entities/Chapter.cs @@ -126,6 +126,11 @@ public class Chapter : IEntityDate, IHasReadTimeEstimate, IHasCoverImage public string WebLinks { get; set; } = string.Empty; public string ISBN { get; set; } = string.Empty; + /// + /// (Kavita+) Average rating from Kavita+ metadata + /// + public float AverageExternalRating { get; set; } = 0f; + #region Locks public bool AgeRatingLocked { get; set; } @@ -171,6 +176,7 @@ public class Chapter : IEntityDate, IHasReadTimeEstimate, IHasCoverImage public int VolumeId { get; set; } public ICollection ExternalReviews { get; set; } = []; + public ICollection ExternalRatings { get; set; } = null!; public void UpdateFrom(ParserInfo info) { @@ -196,8 +202,6 @@ public class Chapter : IEntityDate, IHasReadTimeEstimate, IHasCoverImage /// public string GetNumberTitle() { - // BUG: TODO: On non-english locales, for floats, the range will be 20,5 but the NumberTitle will return 20.5 - // Have I fixed this with TryParse CultureInvariant try { if (MinNumber.Is(MaxNumber)) diff --git a/API/Entities/Enums/RatingAuthority.cs b/API/Entities/Enums/RatingAuthority.cs index 11ffa47a3..0f358a9a7 100644 --- a/API/Entities/Enums/RatingAuthority.cs +++ b/API/Entities/Enums/RatingAuthority.cs @@ -1,7 +1,17 @@ +using System.ComponentModel; + namespace API.Entities.Enums; public enum RatingAuthority { + /// + /// Rating was from a User (internet or local) + /// + [Description("User")] User = 0, + /// + /// Rating was from Professional Critics + /// + [Description("Critic")] Critic = 1, } diff --git a/API/Entities/Metadata/ExternalRating.cs b/API/Entities/Metadata/ExternalRating.cs index b325353e4..9922c7f80 100644 --- a/API/Entities/Metadata/ExternalRating.cs +++ b/API/Entities/Metadata/ExternalRating.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using API.Entities.Enums; using API.Services.Plus; namespace API.Entities.Metadata; @@ -10,8 +11,13 @@ public class ExternalRating public int AverageScore { get; set; } public int FavoriteCount { get; set; } public ScrobbleProvider Provider { get; set; } + public RatingAuthority Authority { get; set; } = RatingAuthority.User; public string? ProviderUrl { get; set; } public int SeriesId { get; set; } + /// + /// This can be null when for a series-rating + /// + public int? ChapterId { get; set; } public ICollection ExternalSeriesMetadatas { get; set; } = null!; } diff --git a/API/Services/Plus/ExternalMetadataService.cs b/API/Services/Plus/ExternalMetadataService.cs index 6159f91ef..199c03a2c 100644 --- a/API/Services/Plus/ExternalMetadataService.cs +++ b/API/Services/Plus/ExternalMetadataService.cs @@ -1085,7 +1085,7 @@ public class ExternalMetadataService : IExternalMetadataService madeModification = await UpdateChapterPeople(chapter, settings, PersonRole.Writer, potentialMatch.Writers) || madeModification; madeModification = await UpdateChapterCoverImage(chapter, settings, potentialMatch.CoverImageUrl) || madeModification; - madeModification = await UpdateExternalChapterMetadata(chapter, settings, potentialMatch) || madeModification; + madeModification = UpdateExternalChapterMetadata(chapter, settings, potentialMatch) || madeModification; _unitOfWork.ChapterRepository.Update(chapter); await _unitOfWork.CommitAsync(); @@ -1094,20 +1094,20 @@ public class ExternalMetadataService : IExternalMetadataService return madeModification; } - private async Task UpdateExternalChapterMetadata(Chapter chapter, MetadataSettingsDto settings, ExternalChapterDto metadata) + private bool UpdateExternalChapterMetadata(Chapter chapter, MetadataSettingsDto settings, ExternalChapterDto metadata) { if (!settings.Enabled) return false; if (metadata.UserReviews.Count == 0 && metadata.CriticReviews.Count == 0) { - _logger.LogDebug("No external reviews found for chapter {ChapterID}", chapter.Id); return false; } + var madeModification = false; + + #region Review _unitOfWork.ExternalSeriesMetadataRepository.Remove(chapter.ExternalReviews); - List externalReviews = []; - externalReviews.AddRange(metadata.CriticReviews .Where(r => !string.IsNullOrWhiteSpace(r.Username) && !string.IsNullOrWhiteSpace(r.Body)) .Select(r => @@ -1115,6 +1115,7 @@ public class ExternalMetadataService : IExternalMetadataService var review = _mapper.Map(r); review.ChapterId = chapter.Id; review.Authority = RatingAuthority.Critic; + CleanCbrReview(ref review); return review; })); externalReviews.AddRange(metadata.UserReviews @@ -1124,13 +1125,55 @@ public class ExternalMetadataService : IExternalMetadataService var review = _mapper.Map(r); review.ChapterId = chapter.Id; review.Authority = RatingAuthority.User; + CleanCbrReview(ref review); return review; })); chapter.ExternalReviews = externalReviews; - + madeModification = externalReviews.Count > 0; _logger.LogDebug("Added {Count} reviews for chapter {ChapterId}", externalReviews.Count, chapter.Id); - return true; + #endregion + + #region Rating + + var averageCriticRating = metadata.CriticReviews.Average(r => r.Rating); + var averageUserRating = metadata.UserReviews.Average(r => r.Rating); + + _unitOfWork.ExternalSeriesMetadataRepository.Remove(chapter.ExternalRatings); + chapter.ExternalRatings = + [ + new ExternalRating + { + AverageScore = (int) averageUserRating, + Provider = ScrobbleProvider.Cbr, + Authority = RatingAuthority.User, + ProviderUrl = metadata.IssueUrl, + }, + new ExternalRating + { + AverageScore = (int) averageCriticRating, + Provider = ScrobbleProvider.Cbr, + Authority = RatingAuthority.Critic, + ProviderUrl = metadata.IssueUrl, + + }, + ]; + + chapter.AverageExternalRating = averageUserRating; + + madeModification = averageUserRating > 0f || averageCriticRating > 0f || madeModification; + + #endregion + + return madeModification; + } + + private static void CleanCbrReview(ref ExternalReview review) + { + // CBR has Read Full Review which links to site, but we already have that + review.Body = review.Body.Replace("Read Full Review", string.Empty).TrimEnd(); + review.RawBody = review.RawBody.Replace("Read Full Review", string.Empty).TrimEnd(); + review.BodyJustText = review.BodyJustText.Replace("Read Full Review", string.Empty).TrimEnd(); } diff --git a/UI/Web/src/app/_models/rating.ts b/UI/Web/src/app/_models/rating.ts index a4c4b79ed..7132706f9 100644 --- a/UI/Web/src/app/_models/rating.ts +++ b/UI/Web/src/app/_models/rating.ts @@ -1,9 +1,15 @@ import {ScrobbleProvider} from "../_services/scrobbling.service"; +export enum RatingAuthority { + User = 0, + Critic = 1, +} + export interface Rating { averageScore: number; meanScore: number; favoriteCount: number; provider: ScrobbleProvider; providerUrl: string | undefined; + authority: RatingAuthority; } diff --git a/UI/Web/src/app/_single-module/match-series-result-item/match-series-result-item.component.html b/UI/Web/src/app/_single-module/match-series-result-item/match-series-result-item.component.html index 15d0c5239..2d94dd848 100644 --- a/UI/Web/src/app/_single-module/match-series-result-item/match-series-result-item.component.html +++ b/UI/Web/src/app/_single-module/match-series-result-item/match-series-result-item.component.html @@ -34,7 +34,11 @@
@if ((item.series.volumes || 0) > 0 || (item.series.chapters || 0) > 0) { {{t('volume-count', {num: item.series.volumes})}} - {{t('chapter-count', {num: item.series.chapters})}} + @if (item.series.plusMediaFormat === PlusMediaFormat.Comic) { + {{t('issue-count', {num: item.series.chapters})}} + } @else { + {{t('chapter-count', {num: item.series.chapters})}} + } } @else { {{t('releasing')}} } diff --git a/UI/Web/src/app/_single-module/match-series-result-item/match-series-result-item.component.ts b/UI/Web/src/app/_single-module/match-series-result-item/match-series-result-item.component.ts index 7dd953ad8..9e3044884 100644 --- a/UI/Web/src/app/_single-module/match-series-result-item/match-series-result-item.component.ts +++ b/UI/Web/src/app/_single-module/match-series-result-item/match-series-result-item.component.ts @@ -14,6 +14,7 @@ import {ReadMoreComponent} from "../../shared/read-more/read-more.component"; import {TranslocoDirective} from "@jsverse/transloco"; import {PlusMediaFormatPipe} from "../../_pipes/plus-media-format.pipe"; import {LoadingComponent} from "../../shared/loading/loading.component"; +import {PlusMediaFormat} from "../../_models/series-detail/external-series-detail"; @Component({ selector: 'app-match-series-result-item', @@ -47,4 +48,5 @@ export class MatchSeriesResultItemComponent { this.selected.emit(this.item); } + protected readonly PlusMediaFormat = PlusMediaFormat; } diff --git a/UI/Web/src/app/_single-module/review-card/user-review.ts b/UI/Web/src/app/_single-module/review-card/user-review.ts index d0c631fe8..58af94dea 100644 --- a/UI/Web/src/app/_single-module/review-card/user-review.ts +++ b/UI/Web/src/app/_single-module/review-card/user-review.ts @@ -1,9 +1,6 @@ import {ScrobbleProvider} from "../../_services/scrobbling.service"; +import {RatingAuthority} from "../../_models/rating"; -export enum RatingAuthority { - User = 0, - Critic = 1 -} export interface UserReview { seriesId: number; diff --git a/UI/Web/src/app/chapter-detail/chapter-detail.component.html b/UI/Web/src/app/chapter-detail/chapter-detail.component.html index ffb69cc67..6e9c68eb7 100644 --- a/UI/Web/src/app/chapter-detail/chapter-detail.component.html +++ b/UI/Web/src/app/chapter-detail/chapter-detail.component.html @@ -29,7 +29,7 @@
| undefined; @ViewChild('companionBar') companionBar: ElementRef | undefined; @@ -165,6 +168,7 @@ export class ChapterDetailComponent implements OnInit { userReviews: Array = []; plusReviews: Array = []; rating: number = 0; + ratings: Array = []; hasBeenRated: boolean = false; weblinks: Array = []; @@ -251,6 +255,7 @@ export class ChapterDetailComponent implements OnInit { this.plusReviews = results.chapterDetail.reviews.filter(r => r.isExternal); this.rating = results.chapterDetail.rating; this.hasBeenRated = results.chapterDetail.hasBeenRated; + this.ratings = results.chapterDetail.ratings; this.themeService.setColorScape(this.chapter.primaryColor, this.chapter.secondaryColor); @@ -389,7 +394,4 @@ export class ChapterDetailComponent implements OnInit { break; } } - - protected readonly LibraryType = LibraryType; - protected readonly encodeURIComponent = encodeURIComponent; } diff --git a/UI/Web/src/app/series-detail/_components/external-rating/external-rating.component.html b/UI/Web/src/app/series-detail/_components/external-rating/external-rating.component.html index cd0194fd8..99f310f1c 100644 --- a/UI/Web/src/app/series-detail/_components/external-rating/external-rating.component.html +++ b/UI/Web/src/app/series-detail/_components/external-rating/external-rating.component.html @@ -17,7 +17,7 @@ @for (rating of ratings; track rating.provider + rating.averageScore) {
+ [popoverTitle]="(rating.provider | scrobbleProviderName) + getAuthorityTitle(rating)" popoverClass="sm-popover"> {{rating.averageScore}}% @@ -70,6 +70,7 @@
} + @if (rating.providerUrl) { {{t('entry-label')}} } diff --git a/UI/Web/src/app/series-detail/_components/external-rating/external-rating.component.ts b/UI/Web/src/app/series-detail/_components/external-rating/external-rating.component.ts index 945ef05ba..8685adc48 100644 --- a/UI/Web/src/app/series-detail/_components/external-rating/external-rating.component.ts +++ b/UI/Web/src/app/series-detail/_components/external-rating/external-rating.component.ts @@ -8,8 +8,7 @@ import { OnInit, ViewEncapsulation } from '@angular/core'; -import {SeriesService} from "../../../_services/series.service"; -import {Rating} from "../../../_models/rating"; +import {Rating, RatingAuthority} from "../../../_models/rating"; import {ProviderImagePipe} from "../../../_pipes/provider-image.pipe"; import {NgbModal, NgbPopover} from "@ng-bootstrap/ng-bootstrap"; import {LoadingComponent} from "../../../shared/loading/loading.component"; @@ -18,13 +17,12 @@ import {NgxStarsModule} from "ngx-stars"; import {ThemeService} from "../../../_services/theme.service"; import {Breakpoint, UtilityService} from "../../../shared/_services/utility.service"; import {ImageComponent} from "../../../shared/image/image.component"; -import {TranslocoDirective} from "@jsverse/transloco"; +import {translate, TranslocoDirective} from "@jsverse/transloco"; import {SafeHtmlPipe} from "../../../_pipes/safe-html.pipe"; import {ImageService} from "../../../_services/image.service"; import {AsyncPipe, NgOptimizedImage, NgTemplateOutlet} from "@angular/common"; import {RatingModalComponent} from "../rating-modal/rating-modal.component"; import {ScrobbleProviderNamePipe} from "../../../_pipes/scrobble-provider-name.pipe"; -import {ChapterService} from "../../../_services/chapter.service"; import {ReviewService} from "../../../_services/review.service"; @Component({ @@ -86,4 +84,14 @@ export class ExternalRatingComponent implements OnInit { this.cdRef.markForCheck(); }); } + + getAuthorityTitle(rating: Rating) { + if (rating.authority === RatingAuthority.Critic) { + return ` (${translate('external-rating.critic')})`; + } + + return ''; + } + + protected readonly RatingAuthority = RatingAuthority; } diff --git a/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.html b/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.html index 450f74aa2..ea08f2262 100644 --- a/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.html +++ b/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.html @@ -36,7 +36,6 @@ [mangaFormat]="series.format"> -