From 5dfcccba7a35e89cab63c152034cafe295d44dd5 Mon Sep 17 00:00:00 2001 From: Joe Milazzo Date: Tue, 2 Jan 2024 18:53:10 -0600 Subject: [PATCH] New Year Bugs (#2513) --- API/Controllers/AccountController.cs | 7 +- API/Controllers/ReviewController.cs | 8 ++- .../Recommendation/ExternalSeriesDetailDto.cs | 2 + API/DTOs/Recommendation/ExternalSeriesDto.cs | 5 +- API/DTOs/SeriesDetail/UpdateUserReviewDto.cs | 2 - API/DTOs/SeriesDetail/UserReviewDto.cs | 1 + API/Helpers/Builders/RatingBuilder.cs | 1 + API/Services/Plus/ScrobblingService.cs | 6 +- API/Services/Tasks/Scanner/ProcessSeries.cs | 4 +- .../app/_interceptors/error.interceptor.ts | 2 +- .../series-detail/external-series-detail.ts | 4 +- .../_models/series-detail/external-series.ts | 3 + UI/Web/src/app/_services/series.service.ts | 4 +- .../review-card-modal.component.html | 4 +- .../review-card-modal.component.ts | 13 ++-- .../review-card/review-card.component.html | 11 ++- .../review-card/review-card.component.scss | 2 +- .../review-card/review-card.component.ts | 6 +- .../review-series-modal.component.html | 17 +++-- .../review-series-modal.component.ts | 19 +++-- .../series-preview-drawer.component.html | 11 ++- .../series-preview-drawer.component.ts | 7 +- .../bulk-operations.component.html | 2 +- .../cards/card-item/card-item.component.html | 34 +++++---- .../cards/card-item/card-item.component.ts | 5 +- .../external-series-card.component.html | 22 +++--- .../external-series-card.component.ts | 7 +- .../carousel-reel.component.html | 57 ++++++++------- .../series-detail.component.html | 7 +- .../series-detail/series-detail.component.ts | 72 ++++++++++++------- UI/Web/src/assets/langs/en.json | 10 +-- openapi.json | 17 +++-- 32 files changed, 230 insertions(+), 142 deletions(-) diff --git a/API/Controllers/AccountController.cs b/API/Controllers/AccountController.cs index dce22c979..5e528c58f 100644 --- a/API/Controllers/AccountController.cs +++ b/API/Controllers/AccountController.cs @@ -318,19 +318,18 @@ public class AccountController : BaseApiController [HttpPost("reset-api-key")] public async Task> ResetApiKey() { - var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername()); - if (user == null) throw new KavitaUnauthenticatedUserException(); - + var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername()) ?? throw new KavitaUnauthenticatedUserException(); user.ApiKey = HashUtil.ApiKey(); if (_unitOfWork.HasChanges() && await _unitOfWork.CommitAsync()) { + await _eventHub.SendMessageToAsync(MessageFactory.UserUpdate, + MessageFactory.UserUpdateEvent(user.Id, user.UserName), user.Id); return Ok(user.ApiKey); } await _unitOfWork.RollbackAsync(); return BadRequest(await _localizationService.Translate(User.GetUserId(), "unable-to-reset-key")); - } diff --git a/API/Controllers/ReviewController.cs b/API/Controllers/ReviewController.cs index 5eaedd6b2..63ff20407 100644 --- a/API/Controllers/ReviewController.cs +++ b/API/Controllers/ReviewController.cs @@ -55,8 +55,10 @@ public class ReviewController : BaseApiController public async Task>> GetReviews(int seriesId) { var userId = User.GetUserId(); + var username = User.GetUsername(); var userRatings = (await _unitOfWork.UserRepository.GetUserRatingDtosForSeriesAsync(seriesId, userId)) - .Where(r => !string.IsNullOrEmpty(r.Body) && !string.IsNullOrEmpty(r.Tagline)) + .Where(r => !string.IsNullOrEmpty(r.Body)) + .OrderByDescending(review => review.Username.Equals(username) ? 1 : 0) .ToList(); if (!await _licenseService.HasActiveLicense()) { @@ -139,7 +141,7 @@ public class ReviewController : BaseApiController var rating = ratingBuilder .WithBody(dto.Body) .WithSeriesId(dto.SeriesId) - .WithTagline(dto.Tagline) + .WithTagline(string.Empty) .Build(); if (rating.Id == 0) @@ -152,7 +154,7 @@ public class ReviewController : BaseApiController BackgroundJob.Enqueue(() => - _scrobblingService.ScrobbleReviewUpdate(user.Id, dto.SeriesId, dto.Tagline, dto.Body)); + _scrobblingService.ScrobbleReviewUpdate(user.Id, dto.SeriesId, string.Empty, dto.Body)); return Ok(_mapper.Map(rating)); } } diff --git a/API/DTOs/Recommendation/ExternalSeriesDetailDto.cs b/API/DTOs/Recommendation/ExternalSeriesDetailDto.cs index a1341b358..9aa852fd7 100644 --- a/API/DTOs/Recommendation/ExternalSeriesDetailDto.cs +++ b/API/DTOs/Recommendation/ExternalSeriesDetailDto.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using API.DTOs.Scrobbling; +using API.Services.Plus; namespace API.DTOs.Recommendation; #nullable enable @@ -19,4 +20,5 @@ public class ExternalSeriesDetailDto public string? Summary { get; set; } public int? VolumeCount { get; set; } public int? ChapterCount { get; set; } + public ScrobbleProvider Provider { get; set; } = ScrobbleProvider.AniList; } diff --git a/API/DTOs/Recommendation/ExternalSeriesDto.cs b/API/DTOs/Recommendation/ExternalSeriesDto.cs index f3ceb1b27..55d2d320c 100644 --- a/API/DTOs/Recommendation/ExternalSeriesDto.cs +++ b/API/DTOs/Recommendation/ExternalSeriesDto.cs @@ -1,4 +1,6 @@ -namespace API.DTOs.Recommendation; +using API.Services.Plus; + +namespace API.DTOs.Recommendation; #nullable enable public class ExternalSeriesDto @@ -9,4 +11,5 @@ public class ExternalSeriesDto public string? Summary { get; set; } public int? AniListId { get; set; } public long? MalId { get; set; } + public ScrobbleProvider Provider { get; set; } = ScrobbleProvider.AniList; } diff --git a/API/DTOs/SeriesDetail/UpdateUserReviewDto.cs b/API/DTOs/SeriesDetail/UpdateUserReviewDto.cs index cb4039368..b25b01672 100644 --- a/API/DTOs/SeriesDetail/UpdateUserReviewDto.cs +++ b/API/DTOs/SeriesDetail/UpdateUserReviewDto.cs @@ -6,7 +6,5 @@ namespace API.DTOs.SeriesDetail; public class UpdateUserReviewDto { public int SeriesId { get; set; } - [MaxLength(120)] - public string? Tagline { get; set; } public string Body { get; set; } } diff --git a/API/DTOs/SeriesDetail/UserReviewDto.cs b/API/DTOs/SeriesDetail/UserReviewDto.cs index 6692c6bd5..c8b2f88c5 100644 --- a/API/DTOs/SeriesDetail/UserReviewDto.cs +++ b/API/DTOs/SeriesDetail/UserReviewDto.cs @@ -12,6 +12,7 @@ public class UserReviewDto /// /// A tagline for the review /// + /// This is not possible to set as a local user public string? Tagline { get; set; } /// diff --git a/API/Helpers/Builders/RatingBuilder.cs b/API/Helpers/Builders/RatingBuilder.cs index 4656c1fa1..54af47ae8 100644 --- a/API/Helpers/Builders/RatingBuilder.cs +++ b/API/Helpers/Builders/RatingBuilder.cs @@ -28,6 +28,7 @@ public class RatingBuilder : IEntityBuilder public RatingBuilder WithTagline(string? tagline) { + if (string.IsNullOrEmpty(tagline)) return this; _rating.Tagline = tagline; return this; } diff --git a/API/Services/Plus/ScrobblingService.cs b/API/Services/Plus/ScrobblingService.cs index d33ccfb19..7c117debc 100644 --- a/API/Services/Plus/ScrobblingService.cs +++ b/API/Services/Plus/ScrobblingService.cs @@ -42,7 +42,7 @@ public interface IScrobblingService Task CheckExternalAccessTokens(); Task HasTokenExpired(int userId, ScrobbleProvider provider); Task ScrobbleRatingUpdate(int userId, int seriesId, float rating); - Task ScrobbleReviewUpdate(int userId, int seriesId, string reviewTitle, string reviewBody); + Task ScrobbleReviewUpdate(int userId, int seriesId, string? reviewTitle, string reviewBody); Task ScrobbleReadingUpdate(int userId, int seriesId); Task ScrobbleWantToReadUpdate(int userId, int seriesId, bool onWantToRead); @@ -185,8 +185,10 @@ public class ScrobblingService : IScrobblingService } ?? string.Empty; } - public async Task ScrobbleReviewUpdate(int userId, int seriesId, string reviewTitle, string reviewBody) + public async Task ScrobbleReviewUpdate(int userId, int seriesId, string? reviewTitle, string reviewBody) { + // Currently disabled until at least hardcover is implemented + return; if (!await _licenseService.HasActiveLicense()) return; var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(seriesId, SeriesIncludes.Metadata | SeriesIncludes.Library); diff --git a/API/Services/Tasks/Scanner/ProcessSeries.cs b/API/Services/Tasks/Scanner/ProcessSeries.cs index cb9ae2916..1cf179139 100644 --- a/API/Services/Tasks/Scanner/ProcessSeries.cs +++ b/API/Services/Tasks/Scanner/ProcessSeries.cs @@ -295,9 +295,9 @@ public class ProcessSeries : IProcessSeries if (series.Format == MangaFormat.Epub || series.Format == MangaFormat.Pdf && chapters.Count == 1) { series.Metadata.MaxCount = 1; - } else if (series.Metadata.TotalCount == 1 && chapters.Count == 1 && chapters[0].IsSpecial) + } else if (series.Metadata.TotalCount <= 1 && chapters.Count == 1 && chapters[0].IsSpecial) { - // If a series has a TotalCount of 1 and there is only a Special, mark it as Complete + // If a series has a TotalCount of 1 (or no total count) and there is only a Special, mark it as Complete series.Metadata.MaxCount = series.Metadata.TotalCount; } else if ((maxChapter == 0 || maxChapter > series.Metadata.TotalCount) && maxVolume <= series.Metadata.TotalCount) { diff --git a/UI/Web/src/app/_interceptors/error.interceptor.ts b/UI/Web/src/app/_interceptors/error.interceptor.ts index 77b27acf0..8f9c31fed 100644 --- a/UI/Web/src/app/_interceptors/error.interceptor.ts +++ b/UI/Web/src/app/_interceptors/error.interceptor.ts @@ -41,7 +41,7 @@ export class ErrorInterceptor implements HttpInterceptor { break; default: // Don't throw multiple Something unexpected went wrong - let genericError = translate('errors.generic'); + const genericError = translate('errors.generic'); if (this.toastr.previousToastMessage !== 'Something unexpected went wrong.' && this.toastr.previousToastMessage !== genericError) { this.toast(genericError); } diff --git a/UI/Web/src/app/_models/series-detail/external-series-detail.ts b/UI/Web/src/app/_models/series-detail/external-series-detail.ts index 1bd008292..85d89c760 100644 --- a/UI/Web/src/app/_models/series-detail/external-series-detail.ts +++ b/UI/Web/src/app/_models/series-detail/external-series-detail.ts @@ -1,3 +1,5 @@ +import {ScrobbleProvider} from "../../_services/scrobbling.service"; + export enum PlusMediaFormat { Manga = 1, Comic = 2, @@ -37,5 +39,5 @@ export interface ExternalSeriesDetail { chapterCount?: number; staff: Array; tags: Array; - + provider: ScrobbleProvider; } diff --git a/UI/Web/src/app/_models/series-detail/external-series.ts b/UI/Web/src/app/_models/series-detail/external-series.ts index 1d0a46bc5..8bf95331f 100644 --- a/UI/Web/src/app/_models/series-detail/external-series.ts +++ b/UI/Web/src/app/_models/series-detail/external-series.ts @@ -1,3 +1,5 @@ +import {ScrobbleProvider} from "../../_services/scrobbling.service"; + export interface ExternalSeries { name: string; coverUrl: string; @@ -5,4 +7,5 @@ export interface ExternalSeries { summary: string; aniListId?: number; malId?: number; + provider: ScrobbleProvider; } diff --git a/UI/Web/src/app/_services/series.service.ts b/UI/Web/src/app/_services/series.service.ts index 6a92a491e..84cda86a9 100644 --- a/UI/Web/src/app/_services/series.service.ts +++ b/UI/Web/src/app/_services/series.service.ts @@ -213,9 +213,9 @@ export class SeriesService { return this.httpClient.get>(this.baseUrl + 'review?seriesId=' + seriesId); } - updateReview(seriesId: number, tagline: string, body: string) { + updateReview(seriesId: number, body: string) { return this.httpClient.post(this.baseUrl + 'review', { - seriesId, tagline, body + seriesId, body }); } diff --git a/UI/Web/src/app/_single-module/review-card-modal/review-card-modal.component.html b/UI/Web/src/app/_single-module/review-card-modal/review-card-modal.component.html index 177e63d11..c76ddacef 100644 --- a/UI/Web/src/app/_single-module/review-card-modal/review-card-modal.component.html +++ b/UI/Web/src/app/_single-module/review-card-modal/review-card-modal.component.html @@ -1,7 +1,9 @@
-
- {{review.tagline.substring(0, 29)}}{{review.tagline.length > 29 ? '…' : ''}} - - {{review.isExternal ? t('external-review') : t('local-review')}} - +
+ {{review.isExternal ? t('external-review') : t('local-review')}}

@@ -23,9 +20,11 @@