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:
Joseph Milazzo 2022-08-16 14:04:21 -05:00 committed by GitHub
parent a3a0b61fc0
commit 9d90652792
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 57 additions and 42 deletions

View File

@ -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
}
}

View File

@ -2014,7 +2014,6 @@ public class ReaderServiceTests
#endregion
#region MarkSeriesAsRead
[Fact]

Binary file not shown.

Binary file not shown.

View File

@ -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" />

View File

@ -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;
}
}
}

View File

@ -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)"

View File

@ -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();
});
}

View File

@ -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) {

View File

@ -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 {

View File

@ -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]);

View File

@ -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">

View File

@ -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">&nbsp;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">&nbsp;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">&nbsp;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">

View File

@ -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];

View File

@ -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();

View File

@ -5,6 +5,7 @@
Want To Read
</h2>
</ng-container>
<h6 subtitle>{{seriesPagination.totalItems}} Series</h6>
</app-side-nav-companion-bar>
</div>

View File

@ -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}`;