Merged main into develop

This commit is contained in:
Joseph Milazzo 2022-04-08 08:16:07 -05:00
commit 848885f103
15 changed files with 41 additions and 13 deletions

View File

@ -9,6 +9,7 @@ using Flurl.Http;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NetVips;
namespace API.Controllers namespace API.Controllers
{ {

View File

@ -1,4 +1,5 @@
using API.Entities.Enums; using System;
using API.Entities.Enums;
namespace API.DTOs.Reader namespace API.DTOs.Reader
{ {

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
using MediatR;
namespace API.DTOs;
public class UpdateUserRole : IRequest<bool>
{
public string Username { get; init; }
public IList<string> Roles { get; init; }
}

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using API.Services; using API.Services;
using Kavita.Common; using Kavita.Common;

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using API.DTOs.CollectionTags; using API.DTOs.CollectionTags;

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using API.Entities.Interfaces; using API.Entities.Interfaces;
using Microsoft.EntityFrameworkCore;
namespace API.Entities namespace API.Entities
{ {

View File

@ -131,6 +131,7 @@ namespace API.Helpers
CreateMap<IEnumerable<ServerSetting>, ServerSettingDto>() CreateMap<IEnumerable<ServerSetting>, ServerSettingDto>()
.ConvertUsing<ServerSettingConverter>(); .ConvertUsing<ServerSettingConverter>();
} }
} }
} }

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Data.Common; using System.Data.Common;
using API.DTOs;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace API.Helpers namespace API.Helpers

View File

@ -19,6 +19,7 @@ using Hangfire;
using Hangfire.MemoryStorage; using Hangfire.MemoryStorage;
using Kavita.Common; using Kavita.Common;
using Kavita.Common.EnvironmentInfo; using Kavita.Common.EnvironmentInfo;
using MediatR;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -131,6 +132,8 @@ namespace API
// Add IHostedService for startup tasks // Add IHostedService for startup tasks
// Any services that should be bootstrapped go here // Any services that should be bootstrapped go here
services.AddHostedService<StartupTasksHostedService>(); services.AddHostedService<StartupTasksHostedService>();
services.AddMediatR(typeof(Startup));
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

BIN
API/config/kavita.db.dik Normal file

Binary file not shown.

BIN
API/config/kavita.db.new Normal file

Binary file not shown.

View File

@ -0,0 +1,4 @@
export interface ScanLibraryEvent {
libraryId: number;
stage: 'complete';
}

View File

@ -107,15 +107,15 @@
</app-drawer> </app-drawer>
</div> </div>
<div #readingSection class="reading-section" [ngStyle]="{'padding-top': topOffset + 20 + 'px'}" <div #readingSection class="reading-section" [ngStyle]="{'padding-top': topOffset + 20 + 'px'}"
[@isLoading]="isLoading ? true : false" (click)="handleReaderClick($event)"> [@isLoading]="isLoading ? true : false" (click)="handleReaderClick($event)">
<div #readingHtml class="book-content" [ngStyle]="{'padding-bottom': topOffset + 20 + 'px', 'margin': '0px 0px'}" <div #readingHtml class="book-content" [ngStyle]="{'padding-bottom': topOffset + 20 + 'px', 'margin': '0px 0px'}"
[innerHtml]="page" *ngIf="page !== undefined"></div> [innerHtml]="page" *ngIf="page !== undefined"></div>
<div class="left {{clickOverlayClass('left')}} no-observe" (click)="prevPage()" *ngIf="clickToPaginate" tabindex="-1"></div> <div class="left {{clickOverlayClass('left')}} no-observe" (click)="prevPage()" *ngIf="clickToPaginate" tabindex="-1"></div>
<div class="{{scrollbarNeeded ? 'right-with-scrollbar' : 'right'}} {{clickOverlayClass('right')}} no-observe" (click)="nextPage()" *ngIf="clickToPaginate" tabindex="-1"></div> <div class="{{scrollbarNeeded ? 'right-with-scrollbar' : 'right'}} {{clickOverlayClass('right')}} no-observe" (click)="nextPage()" *ngIf="clickToPaginate" tabindex="-1"></div>
<div *ngIf="page !== undefined && scrollbarNeeded" (click)="$event.stopPropagation();"> <div *ngIf="page !== undefined && scrollbarNeeded" (click)="$event.stopPropagation();">
<ng-container [ngTemplateOutlet]="actionBar"></ng-container> <ng-container [ngTemplateOutlet]="actionBar"></ng-container>
</div> </div>
@ -123,8 +123,8 @@
<ng-template #actionBar> <ng-template #actionBar>
<div class="reading-bar row g-0 justify-content-between"> <div class="reading-bar row g-0 justify-content-between">
<button class="btn btn-outline-secondary btn-icon col-2 col-xs-1" (click)="prevPage()" <button class="btn btn-outline-secondary btn-icon col-2 col-xs-1" (click)="prevPage()"
[disabled]="IsPrevDisabled" [disabled]="IsPrevDisabled"
title="{{readingDirection === ReadingDirection.LeftToRight ? 'Previous' : 'Next'}} Page"> title="{{readingDirection === ReadingDirection.LeftToRight ? 'Previous' : 'Next'}} Page">
<i class="fa {{(readingDirection === ReadingDirection.LeftToRight ? IsPrevChapter : IsNextChapter) ? 'fa-angle-double-left' : 'fa-angle-left'}}" aria-hidden="true"></i> <i class="fa {{(readingDirection === ReadingDirection.LeftToRight ? IsPrevChapter : IsNextChapter) ? 'fa-angle-double-left' : 'fa-angle-left'}}" aria-hidden="true"></i>
<span class="d-none d-sm-block">&nbsp;{{readingDirection === ReadingDirection.LeftToRight ? 'Previous' : 'Next'}}</span> <span class="d-none d-sm-block">&nbsp;{{readingDirection === ReadingDirection.LeftToRight ? 'Previous' : 'Next'}}</span>
@ -143,8 +143,8 @@
</ng-template> </ng-template>
</div> </div>
<button class="btn btn-secondary col-2 col-xs-1" (click)="closeReader()"><i class="fa fa-times-circle" aria-hidden="true"></i><span class="d-none d-sm-block">&nbsp;Close</span></button> <button class="btn btn-secondary col-2 col-xs-1" (click)="closeReader()"><i class="fa fa-times-circle" aria-hidden="true"></i><span class="d-none d-sm-block">&nbsp;Close</span></button>
<button class="btn btn-outline-secondary btn-icon col-2 col-xs-1" <button class="btn btn-outline-secondary btn-icon col-2 col-xs-1"
[disabled]="IsNextDisabled" [disabled]="IsNextDisabled"
(click)="nextPage()" title="{{readingDirection === ReadingDirection.LeftToRight ? 'Next' : 'Previous'}} Page"> (click)="nextPage()" title="{{readingDirection === ReadingDirection.LeftToRight ? 'Next' : 'Previous'}} Page">
<i class="fa {{(readingDirection === ReadingDirection.LeftToRight ? IsNextChapter : IsPrevChapter) ? 'fa-angle-double-right' : 'fa-angle-right'}}" aria-hidden="true"></i> <i class="fa {{(readingDirection === ReadingDirection.LeftToRight ? IsNextChapter : IsPrevChapter) ? 'fa-angle-double-right' : 'fa-angle-right'}}" aria-hidden="true"></i>
<span class="d-none d-sm-block">{{readingDirection === ReadingDirection.LeftToRight ? 'Next' : 'Previous'}}&nbsp;</span> <span class="d-none d-sm-block">{{readingDirection === ReadingDirection.LeftToRight ? 'Next' : 'Previous'}}&nbsp;</span>
@ -152,4 +152,4 @@
</div> </div>
</ng-template> </ng-template>
</div> </div>

View File

@ -43,7 +43,7 @@ export class CoverImageChooserComponent implements OnInit, OnDestroy {
mode: 'file' | 'url' | 'all' = 'all'; mode: 'file' | 'url' | 'all' = 'all';
private readonly onDestroy = new Subject<void>(); private readonly onDestroy = new Subject<void>();
constructor(public imageService: ImageService, private fb: FormBuilder, private toastr: ToastrService, private uploadService: UploadService, constructor(public imageService: ImageService, private fb: FormBuilder, private toastr: ToastrService, private uploadService: UploadService,
@Inject(DOCUMENT) private document: Document) { } @Inject(DOCUMENT) private document: Document) { }
ngOnInit(): void { ngOnInit(): void {
@ -89,7 +89,7 @@ export class CoverImageChooserComponent implements OnInit, OnDestroy {
img.onload = (e) => this.handleUrlImageAdd(img); img.onload = (e) => this.handleUrlImageAdd(img);
img.onerror = (e) => { img.onerror = (e) => {
this.toastr.error('The image could not be fetched due to server refusing request. Please download and upload from file instead.'); this.toastr.error('The image could not be fetched due to server refusing request. Please download and upload from file instead.');
this.form.get('coverImageUrl')?.setValue(''); this.form.get('coverImageUrl')?.setValue('');
}; };
this.form.get('coverImageUrl')?.setValue(''); this.form.get('coverImageUrl')?.setValue('');
}); });
@ -97,7 +97,7 @@ export class CoverImageChooserComponent implements OnInit, OnDestroy {
} }
changeMode(mode: 'url') { changeMode(mode: 'url') {
this.mode = mode; this.mode = mode;
this.setupEnterHandler(); this.setupEnterHandler();
setTimeout(() => (this.document.querySelector('#load-image') as HTMLInputElement)?.focus(), 10); setTimeout(() => (this.document.querySelector('#load-image') as HTMLInputElement)?.focus(), 10);
@ -164,7 +164,7 @@ export class CoverImageChooserComponent implements OnInit, OnDestroy {
this.loadImage(); this.loadImage();
break; break;
} }
case KEY_CODES.ESC_KEY: case KEY_CODES.ESC_KEY:
this.mode = 'all'; this.mode = 'all';
event.stopPropagation(); event.stopPropagation();

View File

@ -31,6 +31,10 @@ img, .full-width {
height: auto; height: auto;
} }
// .img-container {
// overflow: auto;
// }
@keyframes move-up-down { @keyframes move-up-down {
0%, 100% { 0%, 100% {