mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-05-30 19:54:14 -04:00
More Testing (#2683)
This commit is contained in:
parent
4ce2b4343a
commit
685f7365e1
@ -61,4 +61,23 @@ public class ReviewController : BaseApiController
|
|||||||
_scrobblingService.ScrobbleReviewUpdate(user.Id, dto.SeriesId, string.Empty, dto.Body));
|
_scrobblingService.ScrobbleReviewUpdate(user.Id, dto.SeriesId, string.Empty, dto.Body));
|
||||||
return Ok(_mapper.Map<UserReviewDto>(rating));
|
return Ok(_mapper.Map<UserReviewDto>(rating));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes the user's review for the given series
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpDelete]
|
||||||
|
public async Task<ActionResult> DeleteReview(int seriesId)
|
||||||
|
{
|
||||||
|
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(User.GetUserId(), AppUserIncludes.Ratings);
|
||||||
|
if (user == null) return Unauthorized();
|
||||||
|
|
||||||
|
user.Ratings = user.Ratings.Where(r => r.SeriesId != seriesId).ToList();
|
||||||
|
|
||||||
|
_unitOfWork.UserRepository.Update(user);
|
||||||
|
|
||||||
|
await _unitOfWork.CommitAsync();
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,20 +132,31 @@ public class ExternalSeriesMetadataRepository : IExternalSeriesMetadataRepositor
|
|||||||
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider)
|
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var seriesDetailPlusDto = new SeriesDetailPlusDto()
|
IEnumerable<UserReviewDto> reviews = new List<UserReviewDto>();
|
||||||
|
if (seriesDetailDto.ExternalReviews != null && seriesDetailDto.ExternalReviews.Any())
|
||||||
{
|
{
|
||||||
Ratings = seriesDetailDto.ExternalRatings
|
reviews = seriesDetailDto.ExternalReviews
|
||||||
.DefaultIfEmpty()
|
|
||||||
.Select(r => _mapper.Map<RatingDto>(r)),
|
|
||||||
Reviews = seriesDetailDto.ExternalReviews
|
|
||||||
.DefaultIfEmpty()
|
|
||||||
.OrderByDescending(r => r.Score)
|
|
||||||
.Select(r =>
|
.Select(r =>
|
||||||
{
|
{
|
||||||
var ret = _mapper.Map<UserReviewDto>(r);
|
var ret = _mapper.Map<UserReviewDto>(r);
|
||||||
ret.IsExternal = true;
|
ret.IsExternal = true;
|
||||||
return ret;
|
return ret;
|
||||||
}),
|
})
|
||||||
|
.OrderByDescending(r => r.Score);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<RatingDto> ratings = new List<RatingDto>();
|
||||||
|
if (seriesDetailDto.ExternalRatings != null && seriesDetailDto.ExternalRatings.Any())
|
||||||
|
{
|
||||||
|
ratings = seriesDetailDto.ExternalRatings
|
||||||
|
.Select(r => _mapper.Map<RatingDto>(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var seriesDetailPlusDto = new SeriesDetailPlusDto()
|
||||||
|
{
|
||||||
|
Ratings = ratings,
|
||||||
|
Reviews = reviews,
|
||||||
Recommendations = new RecommendationDto()
|
Recommendations = new RecommendationDto()
|
||||||
{
|
{
|
||||||
ExternalSeries = externalSeriesRecommendations,
|
ExternalSeries = externalSeriesRecommendations,
|
||||||
|
@ -114,7 +114,7 @@ public class ExternalMetadataService : IExternalMetadataService
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var license = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.LicenseKey)).Value;
|
var license = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.LicenseKey)).Value;
|
||||||
var result = await (Configuration.KavitaPlusApiUrl + "/api/metadata/series-detail")
|
var result = await (Configuration.KavitaPlusApiUrl + "/api/metadata/v2/series-detail")
|
||||||
.WithHeader("Accept", "application/json")
|
.WithHeader("Accept", "application/json")
|
||||||
.WithHeader("User-Agent", "Kavita")
|
.WithHeader("User-Agent", "Kavita")
|
||||||
.WithHeader("x-license-key", license)
|
.WithHeader("x-license-key", license)
|
||||||
@ -298,7 +298,7 @@ public class ExternalMetadataService : IExternalMetadataService
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return await (Configuration.KavitaPlusApiUrl + "/api/metadata/series/detail")
|
return await (Configuration.KavitaPlusApiUrl + "/api/metadata/v2/series-by-ids")
|
||||||
.WithHeader("Accept", "application/json")
|
.WithHeader("Accept", "application/json")
|
||||||
.WithHeader("User-Agent", "Kavita")
|
.WithHeader("User-Agent", "Kavita")
|
||||||
.WithHeader("x-license-key", license)
|
.WithHeader("x-license-key", license)
|
||||||
|
@ -10,7 +10,7 @@ namespace API.Services;
|
|||||||
|
|
||||||
public static class ReviewService
|
public static class ReviewService
|
||||||
{
|
{
|
||||||
public static IList<UserReviewDto> SelectSpectrumOfReviews(IList<UserReviewDto> reviews)
|
public static IEnumerable<UserReviewDto> SelectSpectrumOfReviews(IList<UserReviewDto> reviews)
|
||||||
{
|
{
|
||||||
IList<UserReviewDto> externalReviews;
|
IList<UserReviewDto> externalReviews;
|
||||||
var totalReviews = reviews.Count;
|
var totalReviews = reviews.Count;
|
||||||
@ -42,8 +42,9 @@ public static class ReviewService
|
|||||||
externalReviews = reviews;
|
externalReviews = reviews;
|
||||||
}
|
}
|
||||||
|
|
||||||
return externalReviews;
|
return externalReviews.OrderByDescending(r => r.Score);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetCharacters(string body)
|
public static string GetCharacters(string body)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(body)) return body;
|
if (string.IsNullOrEmpty(body)) return body;
|
||||||
|
@ -171,7 +171,7 @@ public class SeriesService : ISeriesService
|
|||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
hasWebLinksChanged =
|
hasWebLinksChanged =
|
||||||
series.Metadata.WebLinks.Equals(updateSeriesMetadataDto.SeriesMetadata?.WebLinks);
|
series.Metadata.WebLinks != updateSeriesMetadataDto.SeriesMetadata?.WebLinks;
|
||||||
series.Metadata.WebLinks = string.Join(",", updateSeriesMetadataDto.SeriesMetadata?.WebLinks
|
series.Metadata.WebLinks = string.Join(",", updateSeriesMetadataDto.SeriesMetadata?.WebLinks
|
||||||
.Split(",")
|
.Split(",")
|
||||||
.Where(s => !string.IsNullOrEmpty(s))
|
.Where(s => !string.IsNullOrEmpty(s))
|
||||||
|
@ -209,16 +209,21 @@ export class SeriesService {
|
|||||||
return this.httpClient.get<SeriesDetail>(this.baseUrl + 'series/series-detail?seriesId=' + seriesId);
|
return this.httpClient.get<SeriesDetail>(this.baseUrl + 'series/series-detail?seriesId=' + seriesId);
|
||||||
}
|
}
|
||||||
|
|
||||||
getReviews(seriesId: number) {
|
|
||||||
return this.httpClient.get<Array<UserReview>>(this.baseUrl + 'review?seriesId=' + seriesId);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
deleteReview(seriesId: number) {
|
||||||
|
return this.httpClient.delete(this.baseUrl + 'review?seriesId=' + seriesId);
|
||||||
|
}
|
||||||
updateReview(seriesId: number, body: string) {
|
updateReview(seriesId: number, body: string) {
|
||||||
return this.httpClient.post<UserReview>(this.baseUrl + 'review', {
|
return this.httpClient.post<UserReview>(this.baseUrl + 'review', {
|
||||||
seriesId, body
|
seriesId, body
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getReviews(seriesId: number) {
|
||||||
|
return this.httpClient.get<Array<UserReview>>(this.baseUrl + 'review?seriesId=' + seriesId);
|
||||||
|
}
|
||||||
|
|
||||||
getRatings(seriesId: number) {
|
getRatings(seriesId: number) {
|
||||||
return this.httpClient.get<Array<Rating>>(this.baseUrl + 'rating?seriesId=' + seriesId);
|
return this.httpClient.get<Array<Rating>>(this.baseUrl + 'rating?seriesId=' + seriesId);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,23 @@
|
|||||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input, OnInit} from '@angular/core';
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
EventEmitter,
|
||||||
|
inject,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
Output
|
||||||
|
} from '@angular/core';
|
||||||
import {CommonModule, NgOptimizedImage} from '@angular/common';
|
import {CommonModule, NgOptimizedImage} from '@angular/common';
|
||||||
import {UserReview} from "./user-review";
|
import {UserReview} from "./user-review";
|
||||||
import {NgbModal} from "@ng-bootstrap/ng-bootstrap";
|
import {NgbModal} from "@ng-bootstrap/ng-bootstrap";
|
||||||
import {ReviewCardModalComponent} from "../review-card-modal/review-card-modal.component";
|
import {ReviewCardModalComponent} from "../review-card-modal/review-card-modal.component";
|
||||||
import {AccountService} from "../../_services/account.service";
|
import {AccountService} from "../../_services/account.service";
|
||||||
import {ReviewSeriesModalComponent} from "../review-series-modal/review-series-modal.component";
|
import {
|
||||||
|
ReviewSeriesModalCloseAction,
|
||||||
|
ReviewSeriesModalCloseEvent,
|
||||||
|
ReviewSeriesModalComponent
|
||||||
|
} from "../review-series-modal/review-series-modal.component";
|
||||||
import {ReadMoreComponent} from "../../shared/read-more/read-more.component";
|
import {ReadMoreComponent} from "../../shared/read-more/read-more.component";
|
||||||
import {DefaultValuePipe} from "../../_pipes/default-value.pipe";
|
import {DefaultValuePipe} from "../../_pipes/default-value.pipe";
|
||||||
import {ImageComponent} from "../../shared/image/image.component";
|
import {ImageComponent} from "../../shared/image/image.component";
|
||||||
@ -25,6 +38,7 @@ export class ReviewCardComponent implements OnInit {
|
|||||||
protected readonly ScrobbleProvider = ScrobbleProvider;
|
protected readonly ScrobbleProvider = ScrobbleProvider;
|
||||||
|
|
||||||
@Input({required: true}) review!: UserReview;
|
@Input({required: true}) review!: UserReview;
|
||||||
|
@Output() refresh = new EventEmitter<ReviewSeriesModalCloseEvent>();
|
||||||
|
|
||||||
isMyReview: boolean = false;
|
isMyReview: boolean = false;
|
||||||
|
|
||||||
@ -48,5 +62,10 @@ export class ReviewCardComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
const ref = this.modalService.open(component, {size: 'lg', fullscreen: 'md'});
|
const ref = this.modalService.open(component, {size: 'lg', fullscreen: 'md'});
|
||||||
ref.componentInstance.review = this.review;
|
ref.componentInstance.review = this.review;
|
||||||
|
ref.closed.subscribe((res: ReviewSeriesModalCloseEvent | undefined) => {
|
||||||
|
if (res) {
|
||||||
|
this.refresh.emit(res);
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-danger" (click)="delete()">{{t('delete')}}</button>
|
||||||
<button class="btn btn-secondary" (click)="close()">{{t('close')}}</button>
|
<button class="btn btn-secondary" (click)="close()">{{t('close')}}</button>
|
||||||
<button type="submit" class="btn btn-primary" (click)="save()">{{t('save')}}</button>
|
<button type="submit" class="btn btn-primary" (click)="save()">{{t('save')}}</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -12,7 +12,21 @@ import {NgbActiveModal, NgbRating} from '@ng-bootstrap/ng-bootstrap';
|
|||||||
import { SeriesService } from 'src/app/_services/series.service';
|
import { SeriesService } from 'src/app/_services/series.service';
|
||||||
import {UserReview} from "../review-card/user-review";
|
import {UserReview} from "../review-card/user-review";
|
||||||
import {CommonModule} from "@angular/common";
|
import {CommonModule} from "@angular/common";
|
||||||
import {TranslocoDirective} from "@ngneat/transloco";
|
import {translate, TranslocoDirective} from "@ngneat/transloco";
|
||||||
|
import {ConfirmService} from "../../shared/confirm.service";
|
||||||
|
import {ToastrService} from "ngx-toastr";
|
||||||
|
|
||||||
|
export enum ReviewSeriesModalCloseAction {
|
||||||
|
Create,
|
||||||
|
Edit,
|
||||||
|
Delete,
|
||||||
|
Close
|
||||||
|
}
|
||||||
|
export interface ReviewSeriesModalCloseEvent {
|
||||||
|
success: boolean,
|
||||||
|
review: UserReview;
|
||||||
|
action: ReviewSeriesModalCloseAction
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-review-series-modal',
|
selector: 'app-review-series-modal',
|
||||||
@ -27,6 +41,8 @@ export class ReviewSeriesModalComponent implements OnInit {
|
|||||||
protected readonly modal = inject(NgbActiveModal);
|
protected readonly modal = inject(NgbActiveModal);
|
||||||
private readonly seriesService = inject(SeriesService);
|
private readonly seriesService = inject(SeriesService);
|
||||||
private readonly cdRef = inject(ChangeDetectorRef);
|
private readonly cdRef = inject(ChangeDetectorRef);
|
||||||
|
private readonly confirmService = inject(ConfirmService);
|
||||||
|
private readonly toastr = inject(ToastrService);
|
||||||
protected readonly minLength = 5;
|
protected readonly minLength = 5;
|
||||||
|
|
||||||
@Input({required: true}) review!: UserReview;
|
@Input({required: true}) review!: UserReview;
|
||||||
@ -40,16 +56,23 @@ export class ReviewSeriesModalComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.modal.close({success: false, review: null});
|
this.modal.close({success: false, review: this.review, action: ReviewSeriesModalCloseAction.Close});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async delete() {
|
||||||
|
if (!await this.confirmService.confirm(translate('toasts.delete-review'))) return;
|
||||||
|
this.seriesService.deleteReview(this.review.seriesId).subscribe(() => {
|
||||||
|
this.toastr.success(translate('toasts.review-deleted'));
|
||||||
|
this.modal.close({success: true, review: this.review, action: ReviewSeriesModalCloseAction.Delete});
|
||||||
|
});
|
||||||
|
}
|
||||||
save() {
|
save() {
|
||||||
const model = this.reviewGroup.value;
|
const model = this.reviewGroup.value;
|
||||||
if (model.reviewBody.length < this.minLength) {
|
if (model.reviewBody.length < this.minLength) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.seriesService.updateReview(this.review.seriesId, model.reviewBody).subscribe(review => {
|
this.seriesService.updateReview(this.review.seriesId, model.reviewBody).subscribe(review => {
|
||||||
this.modal.close({success: true, review: review});
|
this.modal.close({success: true, review: review, action: ReviewSeriesModalCloseAction.Edit});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@
|
|||||||
iconClasses="fa-solid fa-{{getUserReview().length > 0 ? 'pen' : 'plus'}}"
|
iconClasses="fa-solid fa-{{getUserReview().length > 0 ? 'pen' : 'plus'}}"
|
||||||
[clickableTitle]="true" (sectionClick)="openReviewModal()">
|
[clickableTitle]="true" (sectionClick)="openReviewModal()">
|
||||||
<ng-template #carouselItem let-item let-position="idx">
|
<ng-template #carouselItem let-item let-position="idx">
|
||||||
<app-review-card [review]="item"></app-review-card>
|
<app-review-card [review]="item" (refresh)="updateOrDeleteReview($event)"></app-review-card>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</app-carousel-reel>
|
</app-carousel-reel>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,7 +4,8 @@ import {
|
|||||||
DOCUMENT,
|
DOCUMENT,
|
||||||
NgClass,
|
NgClass,
|
||||||
NgFor,
|
NgFor,
|
||||||
NgIf, NgOptimizedImage,
|
NgIf,
|
||||||
|
NgOptimizedImage,
|
||||||
NgStyle,
|
NgStyle,
|
||||||
NgSwitch,
|
NgSwitch,
|
||||||
NgSwitchCase,
|
NgSwitchCase,
|
||||||
@ -44,7 +45,7 @@ import {
|
|||||||
} from '@ng-bootstrap/ng-bootstrap';
|
} from '@ng-bootstrap/ng-bootstrap';
|
||||||
import {ToastrService} from 'ngx-toastr';
|
import {ToastrService} from 'ngx-toastr';
|
||||||
import {catchError, forkJoin, Observable, of} from 'rxjs';
|
import {catchError, forkJoin, Observable, of} from 'rxjs';
|
||||||
import {filter, map, take, tap} from 'rxjs/operators';
|
import {map, take} from 'rxjs/operators';
|
||||||
import {BulkSelectionService} from 'src/app/cards/bulk-selection.service';
|
import {BulkSelectionService} from 'src/app/cards/bulk-selection.service';
|
||||||
import {CardDetailDrawerComponent} from 'src/app/cards/card-detail-drawer/card-detail-drawer.component';
|
import {CardDetailDrawerComponent} from 'src/app/cards/card-detail-drawer/card-detail-drawer.component';
|
||||||
import {EditSeriesModalComponent} from 'src/app/cards/_modals/edit-series-modal/edit-series-modal.component';
|
import {EditSeriesModalComponent} from 'src/app/cards/_modals/edit-series-modal/edit-series-modal.component';
|
||||||
@ -75,7 +76,11 @@ import {ReaderService} from 'src/app/_services/reader.service';
|
|||||||
import {ReadingListService} from 'src/app/_services/reading-list.service';
|
import {ReadingListService} from 'src/app/_services/reading-list.service';
|
||||||
import {ScrollService} from 'src/app/_services/scroll.service';
|
import {ScrollService} from 'src/app/_services/scroll.service';
|
||||||
import {SeriesService} from 'src/app/_services/series.service';
|
import {SeriesService} from 'src/app/_services/series.service';
|
||||||
import {ReviewSeriesModalComponent} from '../../../_single-module/review-series-modal/review-series-modal.component';
|
import {
|
||||||
|
ReviewSeriesModalCloseAction,
|
||||||
|
ReviewSeriesModalCloseEvent,
|
||||||
|
ReviewSeriesModalComponent
|
||||||
|
} from '../../../_single-module/review-series-modal/review-series-modal.component';
|
||||||
import {PageLayoutMode} from 'src/app/_models/page-layout-mode';
|
import {PageLayoutMode} from 'src/app/_models/page-layout-mode';
|
||||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||||
import {UserReview} from "../../../_single-module/review-card/user-review";
|
import {UserReview} from "../../../_single-module/review-card/user-review";
|
||||||
@ -137,7 +142,13 @@ const KavitaPlusSupportedLibraryTypes = [LibraryType.Manga, LibraryType.Book];
|
|||||||
styleUrls: ['./series-detail.component.scss'],
|
styleUrls: ['./series-detail.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgIf, SideNavCompanionBarComponent, CardActionablesComponent, ReactiveFormsModule, NgStyle, TagBadgeComponent, ImageComponent, NgbTooltip, NgbProgressbar, NgbDropdown, NgbDropdownToggle, NgbDropdownMenu, NgbDropdownItem, SeriesMetadataDetailComponent, CarouselReelComponent, ReviewCardComponent, BulkOperationsComponent, NgbNav, NgbNavItem, NgbNavLink, NgbNavContent, VirtualScrollerModule, NgFor, CardItemComponent, ListItemComponent, EntityTitleComponent, SeriesCardComponent, ExternalSeriesCardComponent, ExternalListItemComponent, NgbNavOutlet, LoadingComponent, DecimalPipe, TranslocoDirective, NgTemplateOutlet, NgSwitch, NgSwitchCase, NextExpectedCardComponent, NgClass, NgOptimizedImage, ProviderImagePipe, AsyncPipe]
|
imports: [NgIf, SideNavCompanionBarComponent, CardActionablesComponent, ReactiveFormsModule, NgStyle,
|
||||||
|
TagBadgeComponent, ImageComponent, NgbTooltip, NgbProgressbar, NgbDropdown, NgbDropdownToggle, NgbDropdownMenu,
|
||||||
|
NgbDropdownItem, SeriesMetadataDetailComponent, CarouselReelComponent, ReviewCardComponent, BulkOperationsComponent,
|
||||||
|
NgbNav, NgbNavItem, NgbNavLink, NgbNavContent, VirtualScrollerModule, NgFor, CardItemComponent, ListItemComponent,
|
||||||
|
EntityTitleComponent, SeriesCardComponent, ExternalSeriesCardComponent, ExternalListItemComponent, NgbNavOutlet,
|
||||||
|
LoadingComponent, DecimalPipe, TranslocoDirective, NgTemplateOutlet, NgSwitch, NgSwitchCase, NextExpectedCardComponent,
|
||||||
|
NgClass, NgOptimizedImage, ProviderImagePipe, AsyncPipe]
|
||||||
})
|
})
|
||||||
export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
||||||
|
|
||||||
@ -704,7 +715,7 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
|||||||
if (data.ratings) {
|
if (data.ratings) {
|
||||||
this.ratings = [...data.ratings];
|
this.ratings = [...data.ratings];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Recommendations
|
// Recommendations
|
||||||
if (data.recommendations) {
|
if (data.recommendations) {
|
||||||
@ -854,18 +865,36 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
|||||||
}
|
}
|
||||||
|
|
||||||
modalRef.closed.subscribe((closeResult) => {
|
modalRef.closed.subscribe((closeResult) => {
|
||||||
// BUG: This never executes!
|
this.updateOrDeleteReview(closeResult);
|
||||||
console.log('Close Result: ')
|
|
||||||
if (closeResult.success && closeResult.review !== null) {
|
|
||||||
const index = this.reviews.findIndex(r => r.username === closeResult.review!.username);
|
|
||||||
console.log('update index: ', index, ' with review ', closeResult.review);
|
|
||||||
this.reviews[index] = closeResult.review;
|
|
||||||
this.cdRef.markForCheck();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateOrDeleteReview(closeResult: ReviewSeriesModalCloseEvent) {
|
||||||
|
if (closeResult.action === ReviewSeriesModalCloseAction.Close) return;
|
||||||
|
|
||||||
|
const index = this.reviews.findIndex(r => r.username === closeResult.review!.username);
|
||||||
|
if (closeResult.action === ReviewSeriesModalCloseAction.Edit) {
|
||||||
|
if (index === -1 ) {
|
||||||
|
// A new series was added:
|
||||||
|
this.reviews = [closeResult.review, ...this.reviews];
|
||||||
|
this.cdRef.markForCheck();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// An edit occurred
|
||||||
|
this.reviews[index] = closeResult.review;
|
||||||
|
this.cdRef.markForCheck();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closeResult.action === ReviewSeriesModalCloseAction.Delete) {
|
||||||
|
// An edit occurred
|
||||||
|
this.reviews = [...this.reviews.filter(r => r.username !== closeResult.review!.username)];
|
||||||
|
this.cdRef.markForCheck();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
performAction(action: ActionItem<any>) {
|
performAction(action: ActionItem<any>) {
|
||||||
if (typeof action.callback === 'function') {
|
if (typeof action.callback === 'function') {
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
"review-label": "Review",
|
"review-label": "Review",
|
||||||
"close": "{{common.close}}",
|
"close": "{{common.close}}",
|
||||||
"save": "{{common.save}}",
|
"save": "{{common.save}}",
|
||||||
|
"delete": "{{common.delete}}",
|
||||||
"min-length": "Review must be at least {{count}} characters",
|
"min-length": "Review must be at least {{count}} characters",
|
||||||
"required": "{{validation.required-field}}"
|
"required": "{{validation.required-field}}"
|
||||||
},
|
},
|
||||||
@ -2011,6 +2012,8 @@
|
|||||||
"mark-unread": "Marked as Unread",
|
"mark-unread": "Marked as Unread",
|
||||||
"series-removed-want-to-read": "Series removed from Want to Read list",
|
"series-removed-want-to-read": "Series removed from Want to Read list",
|
||||||
"series-deleted": "Series deleted",
|
"series-deleted": "Series deleted",
|
||||||
|
"delete-review": "Are you sure you want to delete your review?",
|
||||||
|
"review-deleted": "Review deleted",
|
||||||
"file-send-to": "File(s) emailed to {{name}}",
|
"file-send-to": "File(s) emailed to {{name}}",
|
||||||
"theme-missing": "The active theme no longer exists. Please refresh the page.",
|
"theme-missing": "The active theme no longer exists. Please refresh the page.",
|
||||||
"email-sent": "Email sent to {{email}}",
|
"email-sent": "Email sent to {{email}}",
|
||||||
|
23
openapi.json
23
openapi.json
@ -7,7 +7,7 @@
|
|||||||
"name": "GPL-3.0",
|
"name": "GPL-3.0",
|
||||||
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
|
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
|
||||||
},
|
},
|
||||||
"version": "0.7.13.15"
|
"version": "0.7.13.16"
|
||||||
},
|
},
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
@ -7193,6 +7193,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"tags": [
|
||||||
|
"Review"
|
||||||
|
],
|
||||||
|
"summary": "Deletes the user's review for the given series",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "seriesId",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Success"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/Scrobbling/anilist-token": {
|
"/api/Scrobbling/anilist-token": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user