mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-31 14:33:50 -04:00
Merged main into develop
This commit is contained in:
commit
848885f103
@ -9,6 +9,7 @@ using Flurl.Http;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NetVips;
|
||||
|
||||
namespace API.Controllers
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using API.Entities.Enums;
|
||||
using System;
|
||||
using API.Entities.Enums;
|
||||
|
||||
namespace API.DTOs.Reader
|
||||
{
|
||||
|
10
API/DTOs/UpdateUserRole.cs
Normal file
10
API/DTOs/UpdateUserRole.cs
Normal 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; }
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Abstractions;
|
||||
using System.Linq;
|
||||
using API.Services;
|
||||
using Kavita.Common;
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.DTOs.CollectionTags;
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using API.Entities.Interfaces;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace API.Entities
|
||||
{
|
||||
|
@ -131,6 +131,7 @@ namespace API.Helpers
|
||||
|
||||
CreateMap<IEnumerable<ServerSetting>, ServerSettingDto>()
|
||||
.ConvertUsing<ServerSettingConverter>();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using API.DTOs;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace API.Helpers
|
||||
|
@ -19,6 +19,7 @@ using Hangfire;
|
||||
using Hangfire.MemoryStorage;
|
||||
using Kavita.Common;
|
||||
using Kavita.Common.EnvironmentInfo;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@ -131,6 +132,8 @@ namespace API
|
||||
// Add IHostedService for startup tasks
|
||||
// Any services that should be bootstrapped go here
|
||||
services.AddHostedService<StartupTasksHostedService>();
|
||||
|
||||
services.AddMediatR(typeof(Startup));
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
|
BIN
API/config/kavita.db.dik
Normal file
BIN
API/config/kavita.db.dik
Normal file
Binary file not shown.
BIN
API/config/kavita.db.new
Normal file
BIN
API/config/kavita.db.new
Normal file
Binary file not shown.
4
UI/Web/src/app/_models/events/scan-library-event.ts
Normal file
4
UI/Web/src/app/_models/events/scan-library-event.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export interface ScanLibraryEvent {
|
||||
libraryId: number;
|
||||
stage: 'complete';
|
||||
}
|
@ -107,15 +107,15 @@
|
||||
</app-drawer>
|
||||
</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)">
|
||||
|
||||
<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>
|
||||
|
||||
<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 *ngIf="page !== undefined && scrollbarNeeded" (click)="$event.stopPropagation();">
|
||||
<ng-container [ngTemplateOutlet]="actionBar"></ng-container>
|
||||
</div>
|
||||
@ -123,8 +123,8 @@
|
||||
|
||||
<ng-template #actionBar>
|
||||
<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()"
|
||||
[disabled]="IsPrevDisabled"
|
||||
<button class="btn btn-outline-secondary btn-icon col-2 col-xs-1" (click)="prevPage()"
|
||||
[disabled]="IsPrevDisabled"
|
||||
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>
|
||||
<span class="d-none d-sm-block"> {{readingDirection === ReadingDirection.LeftToRight ? 'Previous' : 'Next'}}</span>
|
||||
@ -143,8 +143,8 @@
|
||||
</ng-template>
|
||||
</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"> Close</span></button>
|
||||
<button class="btn btn-outline-secondary btn-icon col-2 col-xs-1"
|
||||
[disabled]="IsNextDisabled"
|
||||
<button class="btn btn-outline-secondary btn-icon col-2 col-xs-1"
|
||||
[disabled]="IsNextDisabled"
|
||||
(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>
|
||||
<span class="d-none d-sm-block">{{readingDirection === ReadingDirection.LeftToRight ? 'Next' : 'Previous'}} </span>
|
||||
@ -152,4 +152,4 @@
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -43,7 +43,7 @@ export class CoverImageChooserComponent implements OnInit, OnDestroy {
|
||||
mode: 'file' | 'url' | 'all' = 'all';
|
||||
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) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
@ -89,7 +89,7 @@ export class CoverImageChooserComponent implements OnInit, OnDestroy {
|
||||
img.onload = (e) => this.handleUrlImageAdd(img);
|
||||
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.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') {
|
||||
this.mode = mode;
|
||||
this.mode = mode;
|
||||
this.setupEnterHandler();
|
||||
|
||||
setTimeout(() => (this.document.querySelector('#load-image') as HTMLInputElement)?.focus(), 10);
|
||||
@ -164,7 +164,7 @@ export class CoverImageChooserComponent implements OnInit, OnDestroy {
|
||||
this.loadImage();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case KEY_CODES.ESC_KEY:
|
||||
this.mode = 'all';
|
||||
event.stopPropagation();
|
||||
|
@ -31,6 +31,10 @@ img, .full-width {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
// .img-container {
|
||||
// overflow: auto;
|
||||
// }
|
||||
|
||||
|
||||
@keyframes move-up-down {
|
||||
0%, 100% {
|
||||
|
Loading…
x
Reference in New Issue
Block a user