mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Release Shakeout Part 1 (#1440)
* Bumped docnet back up, as user issue was not related to the version. Reworked the logic flow for ConfirmEmailToken. Added new test cases for a bug reported around Docnet and weird characters. * Removed a duplicate remove from want to read list * Fixed an issue where series detail didn't appopriately handle remove from want to read. * Added pagination information to want to read, fixed remove from want to read not reloading page * When clearing a series of bookmarks, automatically refresh page. * Added a continue button on reading list page so user can continue where they left off (progress) or start at beginning * Added todo about design idea * Added a bug marker
This commit is contained in:
parent
a3a0b61fc0
commit
9d90652792
@ -22,16 +22,18 @@ namespace API.Tests.Services
|
||||
[InlineData("The Golden Harpoon; Or, Lost Among the Floes A Story of the Whaling Grounds.epub", 16)]
|
||||
[InlineData("Non-existent file.epub", 0)]
|
||||
[InlineData("Non an ebub.pdf", 0)]
|
||||
[InlineData("test_ſ.pdf", 1)] // This is dependent on Docnet bug https://github.com/GowenGit/docnet/issues/80
|
||||
[InlineData("test.pdf", 1)]
|
||||
public void GetNumberOfPagesTest(string filePath, int expectedPages)
|
||||
{
|
||||
var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/BookService/EPUB");
|
||||
var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/BookService");
|
||||
Assert.Equal(expectedPages, _bookService.GetNumberOfPages(Path.Join(testDirectory, filePath)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldHaveComicInfo()
|
||||
{
|
||||
var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/BookService/EPUB");
|
||||
var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/BookService");
|
||||
var archive = Path.Join(testDirectory, "The Golden Harpoon; Or, Lost Among the Floes A Story of the Whaling Grounds.epub");
|
||||
const string summaryInfo = "Book Description";
|
||||
|
||||
@ -44,7 +46,7 @@ namespace API.Tests.Services
|
||||
[Fact]
|
||||
public void ShouldHaveComicInfo_WithAuthors()
|
||||
{
|
||||
var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/BookService/EPUB");
|
||||
var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/BookService");
|
||||
var archive = Path.Join(testDirectory, "The Golden Harpoon; Or, Lost Among the Floes A Story of the Whaling Grounds.epub");
|
||||
|
||||
var comicInfo = _bookService.GetComicInfo(archive);
|
||||
@ -52,16 +54,5 @@ namespace API.Tests.Services
|
||||
Assert.Equal("Roger Starbuck,Junya Inoue", comicInfo.Writer);
|
||||
}
|
||||
|
||||
|
||||
#region BookEscaping
|
||||
|
||||
[Fact]
|
||||
public void EscapeCSSImportReferencesTest()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2014,7 +2014,6 @@ public class ReaderServiceTests
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region MarkSeriesAsRead
|
||||
|
||||
[Fact]
|
||||
|
BIN
API.Tests/Services/Test Data/BookService/test.pdf
Normal file
BIN
API.Tests/Services/Test Data/BookService/test.pdf
Normal file
Binary file not shown.
BIN
API.Tests/Services/Test Data/BookService/test_ſ.pdf
Normal file
BIN
API.Tests/Services/Test Data/BookService/test_ſ.pdf
Normal file
Binary file not shown.
@ -40,7 +40,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
|
||||
<PackageReference Include="Docnet.Core" Version="2.4.0-alpha.2" />
|
||||
<PackageReference Include="Docnet.Core" Version="2.4.0-alpha.4" />
|
||||
<PackageReference Include="ExCSS" Version="4.1.0" />
|
||||
<PackageReference Include="Flurl" Version="3.0.6" />
|
||||
<PackageReference Include="Flurl.Http" Version="3.2.4" />
|
||||
|
@ -727,21 +727,18 @@ namespace API.Controllers
|
||||
private async Task<bool> ConfirmEmailToken(string token, AppUser user)
|
||||
{
|
||||
var result = await _userManager.ConfirmEmailAsync(user, token);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
_logger.LogCritical("Email validation failed");
|
||||
if (result.Errors.Any())
|
||||
{
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
_logger.LogCritical("Email validation error: {Message}", error.Description);
|
||||
}
|
||||
}
|
||||
if (result.Succeeded) return true;
|
||||
|
||||
return false;
|
||||
_logger.LogCritical("[Account] Email validation failed");
|
||||
if (!result.Errors.Any()) return false;
|
||||
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
_logger.LogCritical("[Account] Email validation error: {Message}", error.Description);
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
[isLoading]="loadingBookmarks"
|
||||
[items]="series"
|
||||
[trackByIdentity]="trackByIdentity"
|
||||
[refresh]="refresh"
|
||||
|
||||
>
|
||||
<ng-template #cardItem let-item let-position="idx">
|
||||
<app-card-item [entity]="item" (reload)="loadBookmarks()" [title]="item.name" [imageUrl]="imageService.getSeriesCoverImage(item.id)"
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostListener, OnDestroy, OnInit } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostListener, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { take, Subject } from 'rxjs';
|
||||
@ -30,6 +30,7 @@ export class BookmarksComponent implements OnInit, OnDestroy {
|
||||
actions: ActionItem<Series>[] = [];
|
||||
|
||||
trackByIdentity = (index: number, item: Series) => `${item.name}_${item.localizedName}_${item.pagesRead}`;
|
||||
refresh: EventEmitter<void> = new EventEmitter();
|
||||
|
||||
private onDestroy: Subject<void> = new Subject<void>();
|
||||
|
||||
@ -153,6 +154,7 @@ export class BookmarksComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
this.clearingSeries[series.id] = false;
|
||||
this.toastr.success(series.name + '\'s bookmarks have been removed');
|
||||
this.refresh.emit();
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
@ -146,14 +146,7 @@ export class BulkSelectionService {
|
||||
// else returns volume/chapter items
|
||||
const allowedActions = [Action.AddToReadingList, Action.MarkAsRead, Action.MarkAsUnread, Action.AddToCollection, Action.Delete, Action.AddToWantToReadList, Action.RemoveFromWantToReadList];
|
||||
if (Object.keys(this.selectedCards).filter(item => item === 'series').length > 0) {
|
||||
let actions = this.actionFactory.getSeriesActions(callback).filter(item => allowedActions.includes(item.action));
|
||||
if (this.activeRoute.startsWith('/want-to-read')) {
|
||||
const removeFromWantToRead = {...actions[0]};
|
||||
removeFromWantToRead.action = Action.RemoveFromWantToReadList;
|
||||
removeFromWantToRead.title = 'Remove from Want to Read';
|
||||
actions.push(removeFromWantToRead);
|
||||
}
|
||||
return actions;
|
||||
return this.actionFactory.getSeriesActions(callback).filter(item => allowedActions.includes(item.action));
|
||||
}
|
||||
|
||||
if (Object.keys(this.selectedCards).filter(item => item === 'bookmark').length > 0) {
|
||||
|
@ -44,6 +44,7 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy, OnChanges,
|
||||
@Input() actions: ActionItem<any>[] = [];
|
||||
@Input() trackByIdentity!: TrackByFunction<any>; //(index: number, item: any) => string
|
||||
@Input() filterSettings!: FilterSettings;
|
||||
@Input() refresh!: EventEmitter<void>;
|
||||
|
||||
|
||||
@Input() jumpBarKeys: Array<JumpKey> = []; // This is aprox 784 pixels wide
|
||||
@ -100,6 +101,13 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy, OnChanges,
|
||||
this.pagination = {currentPage: 1, itemsPerPage: this.items.length, totalItems: this.items.length, totalPages: 1};
|
||||
this.changeDetectionRef.markForCheck();
|
||||
}
|
||||
|
||||
if (this.refresh) {
|
||||
this.refresh.subscribe(() => {
|
||||
this.changeDetectionRef.markForCheck();
|
||||
this.virtualScroller.refresh();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { NavigationStart, Router } from '@angular/router';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { filter, take } from 'rxjs/operators';
|
||||
import { Series } from 'src/app/_models/series';
|
||||
import { AccountService } from 'src/app/_services/account.service';
|
||||
import { ImageService } from 'src/app/_services/image.service';
|
||||
@ -102,6 +102,9 @@ export class SeriesCardComponent implements OnInit, OnChanges, OnDestroy {
|
||||
break;
|
||||
case Action.RemoveFromWantToReadList:
|
||||
this.actionService.removeMultipleSeriesFromWantToReadList([series.id]);
|
||||
if (this.router.url.startsWith('/want-to-read')) {
|
||||
this.reload.emit(true);
|
||||
}
|
||||
break;
|
||||
case(Action.AddToCollection):
|
||||
this.actionService.addMultipleSeriesToCollectionTag([series]);
|
||||
|
@ -1,4 +1,5 @@
|
||||
<div cdkDropList class="{{items.length > 0 ? 'example-list list-group-flush' : ''}}" (cdkDropListDropped)="drop($event)">
|
||||
<!-- BUG: https://github.com/angular/components/issues/14098 -->
|
||||
<div class="example-box" *ngFor="let item of items; index as i" cdkDrag [cdkDragData]="item" cdkDragBoundary=".example-list">
|
||||
<div class="d-flex list-container">
|
||||
<div class="me-3 align-middle">
|
||||
|
@ -18,12 +18,18 @@
|
||||
<div class="row g-0 mb-3">
|
||||
<div class="col-auto me-2">
|
||||
<!-- Action row-->
|
||||
<button class="btn btn-primary" title="Read" (click)="read()">
|
||||
<button class="btn btn-primary" title="Read from beginning" (click)="read()">
|
||||
<span>
|
||||
<i class="fa fa-book-open" aria-hidden="true"></i>
|
||||
<i class="fa fa-book" aria-hidden="true"></i>
|
||||
<span class="read-btn--text"> Read</span>
|
||||
</span>
|
||||
</button>
|
||||
<button class="btn btn-primary ms-2" title="Continue from last reading position" (click)="continue()">
|
||||
<span>
|
||||
<i class="fa fa-book-open" aria-hidden="true"></i>
|
||||
<span class="read-btn--text"> Continue</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button class="btn btn-secondary" (click)="removeRead()" [disabled]="readingList.promoted && !this.isAdmin">
|
||||
@ -33,6 +39,7 @@
|
||||
<span class="read-btn--text"> Remove Read</span>
|
||||
</button>
|
||||
</div>
|
||||
<!-- TODO: Move this in companion bar's page actions -->
|
||||
<div class="col-auto ms-2 mt-2" *ngIf="!(readingList?.promoted && !this.isAdmin)">
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="accessibilit-mode" [value]="accessibilityMode" (change)="accessibilityMode = !accessibilityMode">
|
||||
|
@ -176,6 +176,12 @@ export class ReadingListDetailComponent implements OnInit {
|
||||
}
|
||||
|
||||
read() {
|
||||
if (!this.readingList) return;
|
||||
const firstItem = this.items[0];
|
||||
this.router.navigate(this.readerService.getNavigationArray(firstItem.libraryId, firstItem.seriesId, firstItem.chapterId, firstItem.seriesFormat), {queryParams: {readingListId: this.readingList.id}});
|
||||
}
|
||||
|
||||
continue() {
|
||||
// TODO: Can I do this in the backend?
|
||||
if (!this.readingList) return;
|
||||
let currentlyReadingChapter = this.items[0];
|
||||
|
@ -384,6 +384,12 @@ export class SeriesDetailComponent implements OnInit, OnDestroy, AfterContentChe
|
||||
this.changeDetectionRef.markForCheck();
|
||||
});
|
||||
break;
|
||||
case Action.RemoveFromWantToReadList:
|
||||
this.actionService.removeMultipleSeriesFromWantToReadList([series.id], () => {
|
||||
this.actionInProgress = false;
|
||||
this.changeDetectionRef.markForCheck();
|
||||
});
|
||||
break;
|
||||
case (Action.Download):
|
||||
if (this.downloadInProgress) return;
|
||||
this.downloadSeries();
|
||||
|
@ -5,6 +5,7 @@
|
||||
Want To Read
|
||||
</h2>
|
||||
</ng-container>
|
||||
<h6 subtitle>{{seriesPagination.totalItems}} Series</h6>
|
||||
</app-side-nav-companion-bar>
|
||||
</div>
|
||||
|
||||
|
@ -42,7 +42,6 @@ export class WantToReadComponent implements OnInit, OnDestroy {
|
||||
jumpbarKeys: Array<JumpKey> = [];
|
||||
|
||||
filterOpen: EventEmitter<boolean> = new EventEmitter();
|
||||
|
||||
|
||||
private onDestory: Subject<void> = new Subject<void>();
|
||||
trackByIdentity = (index: number, item: Series) => `${item.name}_${item.localizedName}_${item.pagesRead}`;
|
||||
|
Loading…
x
Reference in New Issue
Block a user