Skip to content

Commit

Permalink
Misc Fixes (Kareadita#1031)
Browse files Browse the repository at this point in the history
* Changed the default margin for mobile in book reader to 5%

* Fixed a bug where checking for update did no current version validation before sending the update to the UI.

* Added some documentation to the book code

* Changed token expiry to 2 weeks.

* Search bar will by default not have a border outline

* Cleaned up some styles for white mode hovering on search

* Added missing genre search group, reworked some clearing code, fixed click handlers

* Fixed genre property

* Changed the series title to show bookmarks and the edit button will now take you to series

* Fixed up accordion tabpanel color in dark mode

* Fixed a typo of CoverArtist instead of "Cover artist"

* Added some documentation changes

* Fixed a bug where sort options on All-Series wasn't working

* Added a thanks to Palace-Designs who hosts our infrastructure to the readme.

* Fixed a bug where duplicate people for the same role would be returned

* Fixed a bug where when user cleared out input manually, search would retain old search results
  • Loading branch information
majora2007 authored Feb 4, 2022
1 parent dc2d5b5 commit 19e17c8
Show file tree
Hide file tree
Showing 22 changed files with 130 additions and 55 deletions.
13 changes: 9 additions & 4 deletions API/Controllers/BookController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,16 @@ public async Task<ActionResult> GetBookPageResources(int chapterId, [FromQuery]
return File(content, contentType, $"{chapterId}-{file}");
}

/// <summary>
/// This will return a list of mappings from ID -> page num. ID will be the xhtml key and page num will be the reading order
/// this is used to rewrite anchors in the book text so that we always load properly in FE
/// </summary>
/// <remarks>This is essentially building the table of contents</remarks>
/// <param name="chapterId"></param>
/// <returns></returns>
[HttpGet("{chapterId}/chapters")]
public async Task<ActionResult<ICollection<BookChapterItem>>> GetBookChapters(int chapterId)
{
// This will return a list of mappings from ID -> pagenum. ID will be the xhtml key and pagenum will be the reading order
// this is used to rewrite anchors in the book text so that we always load properly in FE
var chapter = await _unitOfWork.ChapterRepository.GetChapterAsync(chapterId);
using var book = await EpubReader.OpenBookAsync(chapter.Files.ElementAt(0).FilePath);
var mappings = await _bookService.CreateKeyToPageMappingAsync(book);
Expand Down Expand Up @@ -126,7 +131,7 @@ public async Task<ActionResult<ICollection<BookChapterItem>>> GetBookChapters(in
var tocPage = book.Content.Html.Keys.FirstOrDefault(k => k.ToUpper().Contains("TOC"));
if (tocPage == null) return Ok(chaptersList);

// Find all anchor tags, for each anchor we get inner text, to lower then titlecase on UI. Get href and generate page content
// Find all anchor tags, for each anchor we get inner text, to lower then title case on UI. Get href and generate page content
var doc = new HtmlDocument();
var content = await book.Content.Html[tocPage].ReadContentAsync();
doc.LoadHtml(content);
Expand Down Expand Up @@ -252,7 +257,7 @@ public async Task<ActionResult<string>> GetBookPage(int chapterId, [FromQuery] i
return BadRequest("Could not find the appropriate html for that page");
}

private void LogBookErrors(EpubBookRef book, EpubTextContentFileRef contentFileRef, HtmlDocument doc)
private void LogBookErrors(EpubBookRef book, EpubContentFileRef contentFileRef, HtmlDocument doc)
{
_logger.LogError("{FilePath} has an invalid html file (Page {PageName})", book.FilePath, contentFileRef.FileName);
foreach (var error in doc.ParseErrors)
Expand Down
9 changes: 5 additions & 4 deletions API/Controllers/ServerController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,20 @@ public class ServerController : BaseApiController
private readonly IConfiguration _config;
private readonly IBackupService _backupService;
private readonly IArchiveService _archiveService;
private readonly ICacheService _cacheService;
private readonly IVersionUpdaterService _versionUpdaterService;
private readonly IStatsService _statsService;
private readonly ICleanupService _cleanupService;
private readonly IEmailService _emailService;

public ServerController(IHostApplicationLifetime applicationLifetime, ILogger<ServerController> logger, IConfiguration config,
IBackupService backupService, IArchiveService archiveService, ICacheService cacheService,
IVersionUpdaterService versionUpdaterService, IStatsService statsService, ICleanupService cleanupService, IEmailService emailService)
IBackupService backupService, IArchiveService archiveService, IVersionUpdaterService versionUpdaterService, IStatsService statsService,
ICleanupService cleanupService, IEmailService emailService)
{
_applicationLifetime = applicationLifetime;
_logger = logger;
_config = config;
_backupService = backupService;
_archiveService = archiveService;
_cacheService = cacheService;
_versionUpdaterService = versionUpdaterService;
_statsService = statsService;
_cleanupService = cleanupService;
Expand Down Expand Up @@ -111,6 +109,9 @@ public async Task<ActionResult> GetLogs()
}
}

/// <summary>
/// Checks for updates, if no updates that are > current version installed, returns null
/// </summary>
[HttpGet("check-update")]
public async Task<ActionResult<UpdateNotificationDto>> CheckForUpdates()
{
Expand Down
6 changes: 1 addition & 5 deletions API/Data/Repositories/SeriesRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,6 @@ public async Task<PagedList<SeriesDto>> GetSeriesDtoForLibraryIdAsync(int librar
{
var query = await CreateFilteredSearchQueryable(userId, libraryId, filter);

if (filter.SortOptions == null)
{
query = query.OrderBy(s => s.SortName);
}

var retSeries = query
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider)
.AsSplitQuery()
Expand Down Expand Up @@ -314,6 +309,7 @@ public async Task<SearchResultGroupDto> SearchSeries(int userId, bool isAdmin, i
.Where(sm => seriesIds.Contains(sm.SeriesId))
.SelectMany(sm => sm.People.Where(t => EF.Functions.Like(t.Name, $"%{searchQuery}%")))
.AsSplitQuery()
.Distinct()
.ProjectTo<PersonDto>(_mapper.ConfigurationProvider)
.ToListAsync();

Expand Down
5 changes: 5 additions & 0 deletions API/Services/BookService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,11 @@ public static string EscapeTags(string content)
return content;
}

/// <summary>
/// Removes the leading ../
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static string CleanContentKeys(string key)
{
return key.Replace("../", string.Empty);
Expand Down
10 changes: 6 additions & 4 deletions API/Services/Tasks/VersionUpdaterService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ public class VersionUpdaterService : IVersionUpdaterService
private readonly IPresenceTracker _tracker;
private readonly Markdown _markdown = new MarkdownDeep.Markdown();
#pragma warning disable S1075
private static readonly string GithubLatestReleasesUrl = "https://api.github.com/repos/Kareadita/Kavita/releases/latest";
private static readonly string GithubAllReleasesUrl = "https://api.github.com/repos/Kareadita/Kavita/releases";
private const string GithubLatestReleasesUrl = "https://api.github.com/repos/Kareadita/Kavita/releases/latest";
private const string GithubAllReleasesUrl = "https://api.github.com/repos/Kareadita/Kavita/releases";
#pragma warning restore S1075

public VersionUpdaterService(ILogger<VersionUpdaterService> logger, IHubContext<MessageHub> messageHub, IPresenceTracker tracker)
Expand All @@ -76,10 +76,12 @@ public VersionUpdaterService(ILogger<VersionUpdaterService> logger, IHubContext<
/// <summary>
/// Fetches the latest release from Github
/// </summary>
public async Task<UpdateNotificationDto> CheckForUpdate()
/// <returns>Latest update or null if current version is greater than latest update</returns>
public async Task<UpdateNotificationDto?> CheckForUpdate()
{
var update = await GetGithubRelease();
return CreateDto(update);
var dto = CreateDto(update);
return new Version(dto.UpdateVersion) <= new Version(dto.CurrentVersion) ? null : dto;
}

public async Task<IEnumerable<UpdateNotificationDto>> GetAllReleases()
Expand Down
2 changes: 1 addition & 1 deletion API/Services/TokenService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public async Task<string> CreateToken(AppUser user)
var tokenDescriptor = new SecurityTokenDescriptor()
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.Now.AddDays(7),
Expires = DateTime.Now.AddDays(14),
SigningCredentials = creds
};

Expand Down
Binary file added Logo/hosting-sponsor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ your reading collection with your friends and family!
- [x] First class responsive readers that work great on any device (phone, tablet, desktop)
- [x] Dark and Light themes
- [ ] Provide hooks into metadata providers to fetch metadata for Comics, Manga, and Books
- [ ] Metadata should allow for collections, want to read integration from 3rd party services, genres.
- [x] Metadata should allow for collections, want to read integration from 3rd party services, genres.
- [x] Ability to manage users, access, and ratings
- [ ] Ability to sync ratings and reviews to external services
- [x] Fully Accessible with active accessibility audits
Expand Down Expand Up @@ -116,8 +116,12 @@ Thank you to [<img src="/Logo/jetbrains.svg" alt="" width="32"> JetBrains](http:
* [<img src="/Logo/rider.svg" alt="" width="32"> Rider](http://www.jetbrains.com/rider/)
* [<img src="/Logo/dottrace.svg" alt="" width="32"> dotTrace](http://www.jetbrains.com/dottrace/)

## Palace-Designs
We would like to extend a big thank you to [<img src="/Logo/hosting-sponsor.png" alt="" width="128">](https://www.palace-designs.com/) who hosts our infrastructure pro-bono.


### License

* [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
* Copyright 2020-2021
* Copyright 2020-2022

12 changes: 6 additions & 6 deletions UI/Web/src/app/_services/metadata.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,46 +42,46 @@ export class MetadataService {
if (libraries != undefined && libraries.length > 0) {
method += '?libraryIds=' + libraries.join(',');
}
return this.httpClient.get<Array<AgeRatingDto>>(this.baseUrl + method);;
return this.httpClient.get<Array<AgeRatingDto>>(this.baseUrl + method);
}

getAllPublicationStatus(libraries?: Array<number>) {
let method = 'metadata/publication-status'
if (libraries != undefined && libraries.length > 0) {
method += '?libraryIds=' + libraries.join(',');
}
return this.httpClient.get<Array<PublicationStatusDto>>(this.baseUrl + method);;
return this.httpClient.get<Array<PublicationStatusDto>>(this.baseUrl + method);
}

getAllTags(libraries?: Array<number>) {
let method = 'metadata/tags'
if (libraries != undefined && libraries.length > 0) {
method += '?libraryIds=' + libraries.join(',');
}
return this.httpClient.get<Array<Tag>>(this.baseUrl + method);;
return this.httpClient.get<Array<Tag>>(this.baseUrl + method);
}

getAllGenres(libraries?: Array<number>) {
let method = 'metadata/genres'
if (libraries != undefined && libraries.length > 0) {
method += '?libraryIds=' + libraries.join(',');
}
return this.httpClient.get<Genre[]>(this.baseUrl + method);
return this.httpClient.get<Array<Genre>>(this.baseUrl + method);
}

getAllLanguages(libraries?: Array<number>) {
let method = 'metadata/languages'
if (libraries != undefined && libraries.length > 0) {
method += '?libraryIds=' + libraries.join(',');
}
return this.httpClient.get<Language[]>(this.baseUrl + method);
return this.httpClient.get<Array<Language>>(this.baseUrl + method);
}

getAllPeople(libraries?: Array<number>) {
let method = 'metadata/people'
if (libraries != undefined && libraries.length > 0) {
method += '?libraryIds=' + libraries.join(',');
}
return this.httpClient.get<Person[]>(this.baseUrl + method);
return this.httpClient.get<Array<Person>>(this.baseUrl + method);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {

let margin = '15%';
if (windowWidth <= 700) {
margin = '0%';
margin = '5%';
}
if (this.user) {
if (windowWidth > 700) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ <h2 style="display: inline-block">
<span *ngIf="actions.length > 0" class="">
<app-card-actionables (actionHandler)="performAction($event)" [actions]="actions" [labelBy]="header"></app-card-actionables>&nbsp;
</span>{{header}}&nbsp;
<!-- NOTE: On mobile the pill can eat up a lot of space, we can hide it and move to the filter section if user is interested -->
<span class="badge badge-primary badge-pill" attr.aria-label="{{pagination.totalItems}} total items" *ngIf="pagination != undefined">{{pagination.totalItems}}</span>
</h2>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
};
this.collectionSettings.compareFn = (options: CollectionTag[], filter: string) => {
const f = filter.toLowerCase();
return options.filter(m => m.title.toLowerCase() === f);
return options.filter(m => m.title.toLowerCase() === f && this.utilityService.filter(m.title, filter));
}

if (this.filterSettings.presets?.collectionTags && this.filterSettings.presets?.collectionTags.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@
</ul>
</ng-container>

<ng-container *ngIf="genreTemplate !== undefined && grouppedData.genres.length > 0">
<li class="list-group-item section-header"><h5>Genres</h5></li>
<ul class="list-group results">
<li *ngFor="let option of grouppedData.genres; let index = index;" (click)="handleResultlick(option)" tabindex="0"
class="list-group-item" role="option">
<ng-container [ngTemplateOutlet]="genreTemplate" [ngTemplateOutletContext]="{ $implicit: option, idx: index }"></ng-container>
</li>
</ul>
</ng-container>

<ng-container *ngIf="tagTemplate !== undefined && grouppedData.tags.length > 0">
<li class="list-group-item section-header"><h5>Tags</h5></li>
<ul class="list-group results">
Expand All @@ -46,7 +56,7 @@
</ng-container>

<ng-container *ngIf="personTemplate !== undefined && grouppedData.persons.length > 0">
<li class="list-group-item section-header"><h5>Tags</h5></li>
<li class="list-group-item section-header"><h5>People</h5></li>
<ul class="list-group results">
<li *ngFor="let option of grouppedData.persons; let index = index;" (click)="handleResultlick(option)" tabindex="0"
class="list-group-item" role="option">
Expand Down
39 changes: 31 additions & 8 deletions UI/Web/src/app/grouped-typeahead/grouped-typeahead.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,25 @@ input {
width: 100% !important;
}


.typeahead-input {
border: 1px solid #ccc;
border: 1px solid transparent;
border-radius: 4px;
padding: 0px 6px;
display: inline-block;
overflow: hidden;
position: relative;
z-index: 1;
box-sizing: border-box;
box-shadow: none;
border-radius: 4px;
cursor: text;
background-color: #fff;
min-height: 38px;
transition-property: all;
transition-duration: 0.3s;
display: block;


.close {
cursor: pointer;
position: absolute;
Expand Down Expand Up @@ -67,6 +69,7 @@ input {

.typeahead-input.focused {
width: 100%;
border-color: #ccc;
}

/* small devices (phones, 650px and down) */
Expand Down Expand Up @@ -117,7 +120,6 @@ input {
flex: auto;
max-height: calc(100vh - 58px);
height: fit-content;
//background-color: colors.$dark-bg-color;
}

.list-group.results {
Expand Down Expand Up @@ -149,13 +151,34 @@ ul ul {
cursor: pointer;
}

.section-header {
background: colors.$dark-item-accent-bg;
cursor: default;
::ng-deep .bg-dark {
& .section-header {

background: colors.$dark-item-accent-bg;
cursor: default;
}

& .section-header:hover {
background-color: colors.$dark-item-accent-bg !important;
}
}

.section-header:hover {
background-color: colors.$dark-item-accent-bg !important;
::ng-deep .bg-light {
& .section-header {

background: colors.$white-item-accent-bg;
cursor: default;
}

& .section-header:hover, .list-group-item.section-header:hover {
background: colors.$white-item-accent-bg !important;
}

& .list-group-item:hover {
background-color: colors.$primary-color !important;
}


}

.spinner-border {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export class GroupedTypeaheadComponent implements OnInit, OnDestroy {
@ContentChild('collectionTemplate') collectionTemplate: TemplateRef<any> | undefined;
@ContentChild('tagTemplate') tagTemplate: TemplateRef<any> | undefined;
@ContentChild('personTemplate') personTemplate: TemplateRef<any> | undefined;
@ContentChild('genreTemplate') genreTemplate!: TemplateRef<any>;
@ContentChild('noResultsTemplate') noResultsTemplate!: TemplateRef<any>;


Expand Down Expand Up @@ -147,6 +148,7 @@ export class GroupedTypeaheadComponent implements OnInit, OnDestroy {
}

resetField() {
this.prevSearchTerm = '';
this.typeaheadForm.get('typeahead')?.setValue(this.initialValue);
this.clearField.emit();
}
Expand All @@ -159,6 +161,9 @@ export class GroupedTypeaheadComponent implements OnInit, OnDestroy {
return;
}
}
if (this.searchTerm === '') {
this.resetField();
}
this.hasFocus = false;
this.focusChanged.emit(this.hasFocus);
}
Expand All @@ -169,7 +174,8 @@ export class GroupedTypeaheadComponent implements OnInit, OnDestroy {
}

public clear() {
this.resetField();
this.prevSearchTerm = '';
this.typeaheadForm.get('typeahead')?.setValue(this.initialValue);
}

}
Loading

0 comments on commit 19e17c8

Please sign in to comment.