mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-08-05 08:39:59 -04:00
Polish 4 (#3363)
This commit is contained in:
parent
2d5a7a3606
commit
7c4d7dc821
@ -180,13 +180,6 @@ public class SettingsController : BaseApiController
|
||||
_unitOfWork.SettingsRepository.Update(setting);
|
||||
}
|
||||
|
||||
if (setting.Key == ServerSettingKey.CoverImageSize &&
|
||||
updateSettingsDto.CoverImageSize + string.Empty != setting.Value)
|
||||
{
|
||||
setting.Value = updateSettingsDto.CoverImageSize + string.Empty;
|
||||
_unitOfWork.SettingsRepository.Update(setting);
|
||||
}
|
||||
|
||||
if (setting.Key == ServerSettingKey.Port && updateSettingsDto.Port + string.Empty != setting.Value)
|
||||
{
|
||||
if (OsInfo.IsDocker) continue;
|
||||
@ -260,9 +253,16 @@ public class SettingsController : BaseApiController
|
||||
}
|
||||
|
||||
if (setting.Key == ServerSettingKey.EncodeMediaAs &&
|
||||
updateSettingsDto.EncodeMediaAs + string.Empty != setting.Value)
|
||||
((int)updateSettingsDto.EncodeMediaAs).ToString() != setting.Value)
|
||||
{
|
||||
setting.Value = updateSettingsDto.EncodeMediaAs + string.Empty;
|
||||
setting.Value = ((int)updateSettingsDto.EncodeMediaAs).ToString();
|
||||
_unitOfWork.SettingsRepository.Update(setting);
|
||||
}
|
||||
|
||||
if (setting.Key == ServerSettingKey.CoverImageSize &&
|
||||
((int)updateSettingsDto.CoverImageSize).ToString() != setting.Value)
|
||||
{
|
||||
setting.Value = ((int)updateSettingsDto.CoverImageSize).ToString();
|
||||
_unitOfWork.SettingsRepository.Update(setting);
|
||||
}
|
||||
|
||||
|
67
API/Data/ManualMigrations/ManualMigrateEncodeSettings.cs
Normal file
67
API/Data/ManualMigrations/ManualMigrateEncodeSettings.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using Flurl.Util;
|
||||
using Kavita.Common.EnvironmentInfo;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace API.Data.ManualMigrations;
|
||||
|
||||
/// <summary>
|
||||
/// At some point, encoding settings wrote bad data to the backend, maybe in v0.8.0. This just fixes any bad data.
|
||||
/// </summary>
|
||||
public static class ManualMigrateEncodeSettings
|
||||
{
|
||||
public static async Task Migrate(DataContext context, ILogger<Program> logger)
|
||||
{
|
||||
if (await context.ManualMigrationHistory.AnyAsync(m => m.Name == "ManualMigrateEncodeSettings"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
logger.LogCritical("Running ManualMigrateEncodeSettings migration - Please be patient, this may take some time. This is not an error");
|
||||
|
||||
|
||||
var encodeAs = await context.ServerSetting.FirstAsync(s => s.Key == ServerSettingKey.EncodeMediaAs);
|
||||
var coverSize = await context.ServerSetting.FirstAsync(s => s.Key == ServerSettingKey.CoverImageSize);
|
||||
|
||||
var encodeMap = new Dictionary<string, string>
|
||||
{
|
||||
{ EncodeFormat.WEBP.ToString(), ((int)EncodeFormat.WEBP).ToString() },
|
||||
{ EncodeFormat.PNG.ToString(), ((int)EncodeFormat.PNG).ToString() },
|
||||
{ EncodeFormat.AVIF.ToString(), ((int)EncodeFormat.AVIF).ToString() }
|
||||
};
|
||||
|
||||
if (encodeMap.TryGetValue(encodeAs.Value, out var encodedValue))
|
||||
{
|
||||
encodeAs.Value = encodedValue;
|
||||
context.ServerSetting.Update(encodeAs);
|
||||
}
|
||||
|
||||
if (coverSize.Value == "0")
|
||||
{
|
||||
coverSize.Value = ((int)CoverImageSize.Default).ToString();
|
||||
context.ServerSetting.Update(coverSize);
|
||||
}
|
||||
|
||||
|
||||
if (context.ChangeTracker.HasChanges())
|
||||
{
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
await context.ManualMigrationHistory.AddAsync(new ManualMigrationHistory()
|
||||
{
|
||||
Name = "ManualMigrateEncodeSettings",
|
||||
ProductVersion = BuildInfo.Version.ToString(),
|
||||
RanAt = DateTime.UtcNow
|
||||
});
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
logger.LogCritical("Running ManualMigrateEncodeSettings migration - Completed. This is not an error");
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using API.DTOs.Settings;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
@ -33,7 +34,7 @@ public class ServerSettingConverter : ITypeConverter<IEnumerable<ServerSetting>,
|
||||
destination.LoggingLevel = row.Value;
|
||||
break;
|
||||
case ServerSettingKey.Port:
|
||||
destination.Port = int.Parse(row.Value);
|
||||
destination.Port = int.Parse(row.Value, CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case ServerSettingKey.IpAddresses:
|
||||
destination.IpAddresses = row.Value;
|
||||
@ -53,11 +54,8 @@ public class ServerSettingConverter : ITypeConverter<IEnumerable<ServerSetting>,
|
||||
case ServerSettingKey.InstallVersion:
|
||||
destination.InstallVersion = row.Value;
|
||||
break;
|
||||
case ServerSettingKey.EncodeMediaAs:
|
||||
destination.EncodeMediaAs = Enum.Parse<EncodeFormat>(row.Value);
|
||||
break;
|
||||
case ServerSettingKey.TotalBackups:
|
||||
destination.TotalBackups = int.Parse(row.Value);
|
||||
destination.TotalBackups = int.Parse(row.Value, CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case ServerSettingKey.InstallId:
|
||||
destination.InstallId = row.Value;
|
||||
@ -66,33 +64,36 @@ public class ServerSettingConverter : ITypeConverter<IEnumerable<ServerSetting>,
|
||||
destination.EnableFolderWatching = bool.Parse(row.Value);
|
||||
break;
|
||||
case ServerSettingKey.TotalLogs:
|
||||
destination.TotalLogs = int.Parse(row.Value);
|
||||
destination.TotalLogs = int.Parse(row.Value, CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case ServerSettingKey.HostName:
|
||||
destination.HostName = row.Value;
|
||||
break;
|
||||
case ServerSettingKey.CacheSize:
|
||||
destination.CacheSize = long.Parse(row.Value);
|
||||
destination.CacheSize = long.Parse(row.Value, CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case ServerSettingKey.OnDeckProgressDays:
|
||||
destination.OnDeckProgressDays = int.Parse(row.Value);
|
||||
destination.OnDeckProgressDays = int.Parse(row.Value, CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case ServerSettingKey.OnDeckUpdateDays:
|
||||
destination.OnDeckUpdateDays = int.Parse(row.Value);
|
||||
destination.OnDeckUpdateDays = int.Parse(row.Value, CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case ServerSettingKey.CoverImageSize:
|
||||
destination.CoverImageSize = Enum.Parse<CoverImageSize>(row.Value);
|
||||
break;
|
||||
case ServerSettingKey.EncodeMediaAs:
|
||||
destination.EncodeMediaAs = Enum.Parse<EncodeFormat>(row.Value);
|
||||
break;
|
||||
case ServerSettingKey.BackupDirectory:
|
||||
destination.BookmarksDirectory = row.Value;
|
||||
break;
|
||||
case ServerSettingKey.EmailHost:
|
||||
destination.SmtpConfig ??= new SmtpConfigDto();
|
||||
destination.SmtpConfig.Host = row.Value;
|
||||
destination.SmtpConfig.Host = row.Value ?? string.Empty;
|
||||
break;
|
||||
case ServerSettingKey.EmailPort:
|
||||
destination.SmtpConfig ??= new SmtpConfigDto();
|
||||
destination.SmtpConfig.Port = string.IsNullOrEmpty(row.Value) ? 0 : int.Parse(row.Value);
|
||||
destination.SmtpConfig.Port = string.IsNullOrEmpty(row.Value) ? 0 : int.Parse(row.Value, CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case ServerSettingKey.EmailAuthPassword:
|
||||
destination.SmtpConfig ??= new SmtpConfigDto();
|
||||
@ -116,18 +117,22 @@ public class ServerSettingConverter : ITypeConverter<IEnumerable<ServerSetting>,
|
||||
break;
|
||||
case ServerSettingKey.EmailSizeLimit:
|
||||
destination.SmtpConfig ??= new SmtpConfigDto();
|
||||
destination.SmtpConfig.SizeLimit = int.Parse(row.Value);
|
||||
destination.SmtpConfig.SizeLimit = int.Parse(row.Value, CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case ServerSettingKey.EmailCustomizedTemplates:
|
||||
destination.SmtpConfig ??= new SmtpConfigDto();
|
||||
destination.SmtpConfig.CustomizedTemplates = bool.Parse(row.Value);
|
||||
break;
|
||||
case ServerSettingKey.FirstInstallDate:
|
||||
destination.FirstInstallDate = DateTime.Parse(row.Value);
|
||||
destination.FirstInstallDate = DateTime.Parse(row.Value, CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case ServerSettingKey.FirstInstallVersion:
|
||||
destination.FirstInstallVersion = row.Value;
|
||||
break;
|
||||
case ServerSettingKey.LicenseKey:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,9 +127,11 @@ public class ArchiveService : IArchiveService
|
||||
}
|
||||
case ArchiveLibrary.NotSupported:
|
||||
_logger.LogWarning("[GetNumberOfPagesFromArchive] This archive cannot be read: {ArchivePath}. Defaulting to 0 pages", archivePath);
|
||||
_mediaErrorService.ReportMediaIssue(archivePath, MediaErrorProducer.ArchiveService, "File format not supported", string.Empty);
|
||||
return 0;
|
||||
default:
|
||||
_logger.LogWarning("[GetNumberOfPagesFromArchive] There was an exception when reading archive stream: {ArchivePath}. Defaulting to 0 pages", archivePath);
|
||||
_mediaErrorService.ReportMediaIssue(archivePath, MediaErrorProducer.ArchiveService, "File format not supported", string.Empty);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -362,6 +362,7 @@ public class MetadataService : IMetadataService
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Cache this because it's called a lot during scans
|
||||
var settings = await _unitOfWork.SettingsRepository.GetSettingsDtoAsync();
|
||||
var encodeFormat = settings.EncodeMediaAs;
|
||||
var coverImageSize = settings.CoverImageSize;
|
||||
|
@ -99,6 +99,7 @@ public class ReadingItemService : IReadingItemService
|
||||
/// <returns></returns>
|
||||
public int GetNumberOfPages(string filePath, MangaFormat format)
|
||||
{
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case MangaFormat.Archive:
|
||||
|
@ -276,6 +276,7 @@ public class Startup
|
||||
await ManualMigrateRemovePeople.Migrate(dataContext, logger);
|
||||
await MigrateDuplicateDarkTheme.Migrate(dataContext, logger);
|
||||
await ManualMigrateUnscrobbleBookLibraries.Migrate(dataContext, logger);
|
||||
await ManualMigrateEncodeSettings.Migrate(dataContext, logger);
|
||||
|
||||
// Update the version in the DB after all migrations are run
|
||||
var installVersion = await unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.InstallVersion);
|
||||
|
@ -7,9 +7,9 @@
|
||||
<div class="col-auto">
|
||||
@if(!isLoading && allLibraries.length > 0) {
|
||||
<span class="form-check float-end">
|
||||
<input id="select-all" type="checkbox" class="form-check-input"
|
||||
<input id="lib--select-all" type="checkbox" class="form-check-input"
|
||||
[ngModel]="selectAll" (change)="toggleAll()" [indeterminate]="hasSomeSelected">
|
||||
<label for="select-all" class="form-check-label">{{selectAll ? t('deselect-all') : t('select-all')}}</label>
|
||||
<label for="lib--select-all" class="form-check-label">{{selectAll ? t('deselect-all') : t('select-all')}}</label>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
|
@ -4,29 +4,20 @@ import {ToastrService} from 'ngx-toastr';
|
||||
import {debounceTime, distinctUntilChanged, filter, switchMap, take, tap} from 'rxjs';
|
||||
import {SettingsService} from '../settings.service';
|
||||
import {ServerSettings} from '../_models/server-settings';
|
||||
import {
|
||||
NgbAlert,
|
||||
NgbTooltip
|
||||
} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {AsyncPipe, NgTemplateOutlet, TitleCasePipe} from '@angular/common';
|
||||
import {translate, TranslocoModule} from "@jsverse/transloco";
|
||||
import {SafeHtmlPipe} from "../../_pipes/safe-html.pipe";
|
||||
import {ManageMediaIssuesComponent} from "../manage-media-issues/manage-media-issues.component";
|
||||
import {SettingItemComponent} from "../../settings/_components/setting-item/setting-item.component";
|
||||
import {SettingSwitchComponent} from "../../settings/_components/setting-switch/setting-switch.component";
|
||||
import {DefaultValuePipe} from "../../_pipes/default-value.pipe";
|
||||
import {BytesPipe} from "../../_pipes/bytes.pipe";
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
import {CardActionablesComponent} from "../../_single-module/card-actionables/card-actionables.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-manage-email-settings',
|
||||
templateUrl: './manage-email-settings.component.html',
|
||||
styleUrls: ['./manage-email-settings.component.scss'],
|
||||
standalone: true,
|
||||
selector: 'app-manage-email-settings',
|
||||
templateUrl: './manage-email-settings.component.html',
|
||||
styleUrls: ['./manage-email-settings.component.scss'],
|
||||
standalone: true,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [ReactiveFormsModule, NgbTooltip, NgTemplateOutlet, TranslocoModule, SafeHtmlPipe,
|
||||
ManageMediaIssuesComponent, TitleCasePipe, NgbAlert, SettingItemComponent, SettingSwitchComponent, DefaultValuePipe, BytesPipe, AsyncPipe, CardActionablesComponent]
|
||||
imports: [ReactiveFormsModule, TranslocoModule, SettingItemComponent, SettingSwitchComponent, DefaultValuePipe, BytesPipe]
|
||||
})
|
||||
export class ManageEmailSettingsComponent implements OnInit {
|
||||
|
||||
@ -55,8 +46,8 @@ export class ManageEmailSettingsComponent implements OnInit {
|
||||
|
||||
// Automatically save settings as we edit them
|
||||
this.settingsForm.valueChanges.pipe(
|
||||
debounceTime(300),
|
||||
distinctUntilChanged(),
|
||||
debounceTime(100),
|
||||
filter(_ => this.settingsForm.valid),
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
switchMap(_ => {
|
||||
@ -65,7 +56,6 @@ export class ManageEmailSettingsComponent implements OnInit {
|
||||
}),
|
||||
tap(settings => {
|
||||
this.serverSettings = settings;
|
||||
this.resetForm();
|
||||
this.cdRef.markForCheck();
|
||||
})
|
||||
).subscribe();
|
||||
|
@ -6,9 +6,9 @@
|
||||
<div class="col-auto">
|
||||
@if(selectedRoles.length > 0) {
|
||||
<span class="form-check float-end">
|
||||
<input id="select-all" type="checkbox" class="form-check-input"
|
||||
<input id="role--select-all" type="checkbox" class="form-check-input"
|
||||
[ngModel]="selectAll" (change)="toggleAll()" [indeterminate]="hasSomeSelected">
|
||||
<label for="select-all" class="form-check-label">{{selectAll ? t('deselect-all') : t('select-all')}}</label>
|
||||
<label for="role--select-all" class="form-check-label">{{selectAll ? t('deselect-all') : t('select-all')}}</label>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
|
@ -133,21 +133,6 @@ export class AllSeriesComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('document:keydown.shift', ['$event'])
|
||||
handleKeypress(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('document:keyup.shift', ['$event'])
|
||||
handleKeyUp(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
updateFilter(data: FilterEvent) {
|
||||
if (data.filterV2 === undefined) return;
|
||||
this.filter = data.filterV2;
|
||||
|
@ -100,20 +100,6 @@ export class BookmarksComponent implements OnInit {
|
||||
}
|
||||
|
||||
|
||||
@HostListener('document:keydown.shift', ['$event'])
|
||||
handleKeypress(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('document:keyup.shift', ['$event'])
|
||||
handleKeyUp(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
async handleAction(action: ActionItem<Series>, series: Series) {
|
||||
switch (action.action) {
|
||||
case(Action.Delete):
|
||||
|
@ -2,7 +2,7 @@ import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
DestroyRef,
|
||||
DestroyRef, HostListener,
|
||||
inject,
|
||||
Input,
|
||||
OnInit
|
||||
@ -14,6 +14,7 @@ import {AsyncPipe, DecimalPipe, NgStyle} from "@angular/common";
|
||||
import {TranslocoModule} from "@jsverse/transloco";
|
||||
import {NgbTooltip} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {CardActionablesComponent} from "../../_single-module/card-actionables/card-actionables.component";
|
||||
import {KEY_CODES} from "../../shared/_services/utility.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-bulk-operations',
|
||||
@ -55,7 +56,20 @@ export class BulkOperationsComponent implements OnInit {
|
||||
public readonly bulkSelectionService = inject(BulkSelectionService);
|
||||
protected readonly Action = Action;
|
||||
|
||||
constructor() { }
|
||||
@HostListener('document:keydown.shift', ['$event'])
|
||||
handleKeypress(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = true;
|
||||
}
|
||||
// TODO: See if we can figure out a select all (Ctrl+A) by having each method handle the event or pass all the data into this component.
|
||||
}
|
||||
|
||||
@HostListener('document:keyup.shift', ['$event'])
|
||||
handleKeyUp(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.bulkSelectionService.actions$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(actions => {
|
||||
|
@ -81,20 +81,6 @@ export class AllCollectionsComponent implements OnInit {
|
||||
trackByIdentity = (index: number, item: UserCollection) => `${item.id}_${item.title}_${item.owner}_${item.promoted}`;
|
||||
user!: User;
|
||||
|
||||
@HostListener('document:keydown.shift', ['$event'])
|
||||
handleKeypress(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('document:keyup.shift', ['$event'])
|
||||
handleKeyUp(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
constructor() {
|
||||
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
|
||||
|
@ -234,20 +234,6 @@ export class CollectionDetailComponent implements OnInit, AfterContentChecked {
|
||||
this.scrollService.setScrollContainer(this.scrollingBlock);
|
||||
}
|
||||
|
||||
@HostListener('document:keydown.shift', ['$event'])
|
||||
handleKeypress(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('document:keyup.shift', ['$event'])
|
||||
handleKeyUp(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
updateTag(tagId: number) {
|
||||
this.collectionService.allCollections().subscribe(tags => {
|
||||
const matchingTags = tags.filter(t => t.id === tagId);
|
||||
|
@ -29,12 +29,10 @@ import {FilterSettings} from '../metadata-filter/filter-settings';
|
||||
import {JumpKey} from '../_models/jumpbar/jump-key';
|
||||
import {SeriesRemovedEvent} from '../_models/events/series-removed-event';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
import {SentenceCasePipe} from '../_pipes/sentence-case.pipe';
|
||||
import {BulkOperationsComponent} from '../cards/bulk-operations/bulk-operations.component';
|
||||
import {SeriesCardComponent} from '../cards/series-card/series-card.component';
|
||||
import {CardDetailLayoutComponent} from '../cards/card-detail-layout/card-detail-layout.component';
|
||||
import {DecimalPipe} from '@angular/common';
|
||||
import {NgbNav, NgbNavContent, NgbNavItem, NgbNavItemRole, NgbNavLink, NgbNavOutlet} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {
|
||||
SideNavCompanionBarComponent
|
||||
} from '../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component';
|
||||
@ -52,8 +50,8 @@ import {debounceTime, ReplaySubject, tap} from "rxjs";
|
||||
styleUrls: ['./library-detail.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [SideNavCompanionBarComponent, CardActionablesComponent, NgbNav, NgbNavItem, NgbNavItemRole, NgbNavLink, NgbNavContent,
|
||||
CardDetailLayoutComponent, SeriesCardComponent, BulkOperationsComponent, NgbNavOutlet, DecimalPipe, SentenceCasePipe, TranslocoDirective, LoadingComponent]
|
||||
imports: [SideNavCompanionBarComponent, CardActionablesComponent,
|
||||
CardDetailLayoutComponent, SeriesCardComponent, BulkOperationsComponent, DecimalPipe, TranslocoDirective, LoadingComponent]
|
||||
})
|
||||
export class LibraryDetailComponent implements OnInit {
|
||||
|
||||
|
@ -11,7 +11,7 @@ import {
|
||||
} from '@angular/core';
|
||||
import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms';
|
||||
import {FilterStatement} from '../../../_models/metadata/v2/filter-statement';
|
||||
import {BehaviorSubject, distinctUntilChanged, filter, map, Observable, of, startWith, switchMap} from 'rxjs';
|
||||
import {BehaviorSubject, distinctUntilChanged, filter, map, Observable, of, startWith, switchMap, tap} from 'rxjs';
|
||||
import {MetadataService} from 'src/app/_services/metadata.service';
|
||||
import {mangaFormatFilters} from 'src/app/_models/metadata/series-filter';
|
||||
import {PersonRole} from 'src/app/_models/metadata/person';
|
||||
@ -135,11 +135,8 @@ const BooleanComparisons = [
|
||||
FilterFieldPipe,
|
||||
FilterComparisonPipe,
|
||||
Select2Module,
|
||||
NgTemplateOutlet,
|
||||
TagBadgeComponent,
|
||||
NgbTooltip,
|
||||
TranslocoDirective,
|
||||
NgbDatepicker,
|
||||
NgbInputDatepicker
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
@ -207,9 +204,11 @@ export class MetadataFilterRowComponent implements OnInit {
|
||||
);
|
||||
|
||||
|
||||
this.formGroup!.valueChanges.pipe(distinctUntilChanged(), takeUntilDestroyed(this.destroyRef)).subscribe(_ => {
|
||||
this.propagateFilterUpdate();
|
||||
});
|
||||
this.formGroup!.valueChanges.pipe(
|
||||
distinctUntilChanged(),
|
||||
tap(_ => this.propagateFilterUpdate()),
|
||||
takeUntilDestroyed(this.destroyRef)
|
||||
).subscribe();
|
||||
|
||||
this.loaded = true;
|
||||
this.cdRef.markForCheck();
|
||||
@ -336,13 +335,13 @@ export class MetadataFilterRowComponent implements OnInit {
|
||||
|
||||
|
||||
if (StringFields.includes(inputVal)) {
|
||||
const comps = [...StringComparisons];
|
||||
let comps = [...StringComparisons];
|
||||
|
||||
if (FieldsThatShouldIncludeIsEmpty.includes(inputVal)) {
|
||||
comps.push(FilterComparison.IsEmpty);
|
||||
}
|
||||
|
||||
this.validComparisons$.next(comps);
|
||||
this.validComparisons$.next([...new Set(comps)]);
|
||||
this.predicateType$.next(PredicateType.Text);
|
||||
|
||||
if (this.loaded) {
|
||||
@ -362,7 +361,7 @@ export class MetadataFilterRowComponent implements OnInit {
|
||||
comps.push(FilterComparison.IsEmpty);
|
||||
}
|
||||
|
||||
this.validComparisons$.next(comps);
|
||||
this.validComparisons$.next([...new Set(comps)]);
|
||||
this.predicateType$.next(PredicateType.Number);
|
||||
if (this.loaded) {
|
||||
this.formGroup.get('filterValue')?.patchValue(0);
|
||||
@ -377,7 +376,7 @@ export class MetadataFilterRowComponent implements OnInit {
|
||||
comps.push(FilterComparison.IsEmpty);
|
||||
}
|
||||
|
||||
this.validComparisons$.next(comps);
|
||||
this.validComparisons$.next([...new Set(comps)]);
|
||||
this.predicateType$.next(PredicateType.Date);
|
||||
|
||||
if (this.loaded) {
|
||||
@ -388,12 +387,13 @@ export class MetadataFilterRowComponent implements OnInit {
|
||||
}
|
||||
|
||||
if (BooleanFields.includes(inputVal)) {
|
||||
const comps = [...DateComparisons];
|
||||
let comps = [...DateComparisons];
|
||||
if (FieldsThatShouldIncludeIsEmpty.includes(inputVal)) {
|
||||
comps.push(FilterComparison.IsEmpty);
|
||||
}
|
||||
|
||||
this.validComparisons$.next(comps);
|
||||
|
||||
this.validComparisons$.next([...new Set(comps)]);
|
||||
this.predicateType$.next(PredicateType.Boolean);
|
||||
|
||||
if (this.loaded) {
|
||||
@ -415,7 +415,7 @@ export class MetadataFilterRowComponent implements OnInit {
|
||||
comps.push(FilterComparison.IsEmpty);
|
||||
}
|
||||
|
||||
this.validComparisons$.next(comps);
|
||||
this.validComparisons$.next([...new Set(comps)]);
|
||||
this.predicateType$.next(PredicateType.Dropdown);
|
||||
if (this.loaded) {
|
||||
this.formGroup.get('filterValue')?.patchValue(0);
|
||||
|
@ -49,19 +49,6 @@ export class ReadingListsComponent implements OnInit {
|
||||
globalActions: Array<ActionItem<any>> = [];
|
||||
trackByIdentity = (index: number, item: ReadingList) => `${item.id}_${item.title}_${item.promoted}`;
|
||||
|
||||
@HostListener('document:keydown.shift', ['$event'])
|
||||
handleKeypress(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('document:keyup.shift', ['$event'])
|
||||
handleKeyUp(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
constructor(private readingListService: ReadingListService, public imageService: ImageService, private actionFactoryService: ActionFactoryService,
|
||||
private accountService: AccountService, private toastr: ToastrService, private router: Router,
|
||||
|
@ -2,11 +2,9 @@ import {
|
||||
ChangeDetectionStrategy, ChangeDetectorRef,
|
||||
Component,
|
||||
DestroyRef,
|
||||
EventEmitter,
|
||||
inject,
|
||||
Input,
|
||||
OnInit,
|
||||
Output
|
||||
} from '@angular/core';
|
||||
import {AsyncPipe} from "@angular/common";
|
||||
import {Observable, shareReplay, tap} from "rxjs";
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
import {SeriesService} from "../../../_services/series.service";
|
||||
import {Rating} from "../../../_models/rating";
|
||||
import {ProviderImagePipe} from "../../../_pipes/provider-image.pipe";
|
||||
import {NgbModal, NgbPopover, NgbRating} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {NgbModal, NgbPopover} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {LoadingComponent} from "../../../shared/loading/loading.component";
|
||||
import {LibraryType} from "../../../_models/library/library";
|
||||
import {ProviderNamePipe} from "../../../_pipes/provider-name.pipe";
|
||||
@ -22,13 +22,13 @@ import {TranslocoDirective} from "@jsverse/transloco";
|
||||
import {SafeHtmlPipe} from "../../../_pipes/safe-html.pipe";
|
||||
import {ImageService} from "../../../_services/image.service";
|
||||
import {AsyncPipe, NgOptimizedImage, NgTemplateOutlet} from "@angular/common";
|
||||
import {InviteUserComponent} from "../../../admin/invite-user/invite-user.component";
|
||||
import {RatingModalComponent} from "../rating-modal/rating-modal.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-external-rating',
|
||||
standalone: true,
|
||||
imports: [ProviderImagePipe, NgbRating, NgbPopover, LoadingComponent, ProviderNamePipe, NgxStarsModule, ImageComponent, TranslocoDirective, SafeHtmlPipe, NgOptimizedImage, AsyncPipe, NgTemplateOutlet],
|
||||
imports: [ProviderImagePipe, NgbPopover, LoadingComponent, ProviderNamePipe, NgxStarsModule, ImageComponent,
|
||||
TranslocoDirective, SafeHtmlPipe, NgOptimizedImage, AsyncPipe, NgTemplateOutlet],
|
||||
templateUrl: './external-rating.component.html',
|
||||
styleUrls: ['./external-rating.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
@ -15,9 +15,7 @@ import {ImageService} from "../../../_services/image.service";
|
||||
import {FilterUtilitiesService} from "../../../shared/_services/filter-utilities.service";
|
||||
import {FilterComparison} from "../../../_models/metadata/v2/filter-comparison";
|
||||
import {FilterField} from "../../../_models/metadata/v2/filter-field";
|
||||
import {MangaFormatPipe} from "../../../_pipes/manga-format.pipe";
|
||||
import {MangaFormat} from "../../../_models/manga-format";
|
||||
import {MangaFormatIconPipe} from "../../../_pipes/manga-format-icon.pipe";
|
||||
import {SeriesFormatComponent} from "../../../shared/series-format/series-format.component";
|
||||
import {PublisherFlipperComponent} from "../../../_single-modules/publisher-flipper/publisher-flipper.component";
|
||||
|
||||
@ -32,8 +30,6 @@ import {PublisherFlipperComponent} from "../../../_single-modules/publisher-flip
|
||||
NgbTooltip,
|
||||
TranslocoDirective,
|
||||
ImageComponent,
|
||||
MangaFormatPipe,
|
||||
MangaFormatIconPipe,
|
||||
SeriesFormatComponent,
|
||||
PublisherFlipperComponent
|
||||
],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {ChangeDetectionStrategy, Component, ContentChild, inject, Input, TemplateRef} from '@angular/core';
|
||||
import {CommonModule, NgTemplateOutlet} from '@angular/common';
|
||||
import {NgTemplateOutlet} from '@angular/common';
|
||||
import {A11yClickDirective} from "../../../shared/a11y-click.directive";
|
||||
import {BadgeExpanderComponent} from "../../../shared/badge-expander/badge-expander.component";
|
||||
import {TagBadgeComponent, TagBadgeCursor} from "../../../shared/tag-badge/tag-badge.component";
|
||||
|
@ -1,11 +1,8 @@
|
||||
import {
|
||||
AsyncPipe,
|
||||
DecimalPipe,
|
||||
DOCUMENT,
|
||||
JsonPipe,
|
||||
Location,
|
||||
NgClass,
|
||||
NgOptimizedImage,
|
||||
NgStyle,
|
||||
NgTemplateOutlet
|
||||
} from '@angular/common';
|
||||
@ -37,7 +34,6 @@ import {
|
||||
NgbNavItem,
|
||||
NgbNavLink,
|
||||
NgbNavOutlet,
|
||||
NgbProgressbar,
|
||||
NgbTooltip
|
||||
} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {ToastrService} from 'ngx-toastr';
|
||||
@ -81,30 +77,20 @@ import {
|
||||
import {PageLayoutMode} from 'src/app/_models/page-layout-mode';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
import {UserReview} from "../../../_single-module/review-card/user-review";
|
||||
import {LoadingComponent} from '../../../shared/loading/loading.component';
|
||||
import {ExternalSeriesCardComponent} from '../../../cards/external-series-card/external-series-card.component';
|
||||
import {SeriesCardComponent} from '../../../cards/series-card/series-card.component';
|
||||
import {EntityTitleComponent} from '../../../cards/entity-title/entity-title.component';
|
||||
import {CardItemComponent} from '../../../cards/card-item/card-item.component';
|
||||
import {VirtualScrollerModule} from '@iharbeck/ngx-virtual-scroller';
|
||||
import {BulkOperationsComponent} from '../../../cards/bulk-operations/bulk-operations.component';
|
||||
import {ReviewCardComponent} from '../../../_single-module/review-card/review-card.component';
|
||||
import {CarouselReelComponent} from '../../../carousel/_components/carousel-reel/carousel-reel.component';
|
||||
import {ImageComponent} from '../../../shared/image/image.component';
|
||||
import {TagBadgeComponent} from '../../../shared/tag-badge/tag-badge.component';
|
||||
import {
|
||||
SideNavCompanionBarComponent
|
||||
} from '../../../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component';
|
||||
import {translate, TranslocoDirective, TranslocoService} from "@jsverse/transloco";
|
||||
import {CardActionablesComponent} from "../../../_single-module/card-actionables/card-actionables.component";
|
||||
import {PublicationStatus} from "../../../_models/metadata/publication-status";
|
||||
import {NextExpectedChapter} from "../../../_models/series-detail/next-expected-chapter";
|
||||
import {NextExpectedCardComponent} from "../../../cards/next-expected-card/next-expected-card.component";
|
||||
import {ProviderImagePipe} from "../../../_pipes/provider-image.pipe";
|
||||
import {MetadataService} from "../../../_services/metadata.service";
|
||||
import {Rating} from "../../../_models/rating";
|
||||
import {ThemeService} from "../../../_services/theme.service";
|
||||
import {PersonBadgeComponent} from "../../../shared/person-badge/person-badge.component";
|
||||
import {DetailsTabComponent} from "../../../_single-module/details-tab/details-tab.component";
|
||||
import {
|
||||
EditChapterModalCloseResult,
|
||||
@ -116,23 +102,14 @@ import {VolumeCardComponent} from "../../../cards/volume-card/volume-card.compon
|
||||
import {SettingsTabId} from "../../../sidenav/preference-nav/preference-nav.component";
|
||||
import {FilterField} from "../../../_models/metadata/v2/filter-field";
|
||||
import {AgeRating} from "../../../_models/metadata/age-rating";
|
||||
import {AgeRatingPipe} from "../../../_pipes/age-rating.pipe";
|
||||
import {DefaultValuePipe} from "../../../_pipes/default-value.pipe";
|
||||
import {ExternalRatingComponent} from "../external-rating/external-rating.component";
|
||||
import {ReadMoreComponent} from "../../../shared/read-more/read-more.component";
|
||||
import {ReadTimePipe} from "../../../_pipes/read-time.pipe";
|
||||
import {FilterComparison} from "../../../_models/metadata/v2/filter-comparison";
|
||||
import {FilterUtilitiesService} from "../../../shared/_services/filter-utilities.service";
|
||||
import {TimeAgoPipe} from "../../../_pipes/time-ago.pipe";
|
||||
import {AgeRatingImageComponent} from "../../../_single-modules/age-rating-image/age-rating-image.component";
|
||||
import {CompactNumberPipe} from "../../../_pipes/compact-number.pipe";
|
||||
import {IconAndTitleComponent} from "../../../shared/icon-and-title/icon-and-title.component";
|
||||
import {SafeHtmlPipe} from "../../../_pipes/safe-html.pipe";
|
||||
import {BadgeExpanderComponent} from "../../../shared/badge-expander/badge-expander.component";
|
||||
import {A11yClickDirective} from "../../../shared/a11y-click.directive";
|
||||
import {ScrobblingService} from "../../../_services/scrobbling.service";
|
||||
import {HourEstimateRange} from "../../../_models/series-detail/hour-estimate-range";
|
||||
import {ReadTimeLeftPipe} from "../../../_pipes/read-time-left.pipe";
|
||||
import {PublicationStatusPipe} from "../../../_pipes/publication-status.pipe";
|
||||
import {MetadataDetailRowComponent} from "../metadata-detail-row/metadata-detail-row.component";
|
||||
import {DownloadButtonComponent} from "../download-button/download-button.component";
|
||||
@ -142,8 +119,6 @@ import {CoverUpdateEvent} from "../../../_models/events/cover-update-event";
|
||||
import {RelatedSeriesPair, RelatedTabComponent} from "../../../_single-modules/related-tab/related-tab.component";
|
||||
import {CollectionTagService} from "../../../_services/collection-tag.service";
|
||||
import {UserCollection} from "../../../_models/collection-tag";
|
||||
import {SeriesFormatComponent} from "../../../shared/series-format/series-format.component";
|
||||
import {MangaFormatPipe} from "../../../_pipes/manga-format.pipe";
|
||||
import {CoverImageComponent} from "../../../_single-module/cover-image/cover-image.component";
|
||||
import {DefaultModalOptions} from "../../../_models/default-modal-options";
|
||||
|
||||
@ -171,16 +146,14 @@ interface StoryLineItem {
|
||||
styleUrls: ['./series-detail.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [SideNavCompanionBarComponent, CardActionablesComponent, ReactiveFormsModule, NgStyle,
|
||||
TagBadgeComponent, ImageComponent, NgbTooltip, NgbProgressbar, NgbDropdown, NgbDropdownToggle, NgbDropdownMenu,
|
||||
imports: [CardActionablesComponent, ReactiveFormsModule, NgStyle,
|
||||
NgbTooltip, NgbDropdown, NgbDropdownToggle, NgbDropdownMenu,
|
||||
NgbDropdownItem, CarouselReelComponent, ReviewCardComponent, BulkOperationsComponent,
|
||||
NgbNav, NgbNavItem, NgbNavLink, NgbNavContent, VirtualScrollerModule, CardItemComponent,
|
||||
EntityTitleComponent, SeriesCardComponent, ExternalSeriesCardComponent, NgbNavOutlet,
|
||||
LoadingComponent, DecimalPipe, TranslocoDirective, NgTemplateOutlet, NextExpectedCardComponent,
|
||||
NgClass, NgOptimizedImage, ProviderImagePipe, AsyncPipe, PersonBadgeComponent, DetailsTabComponent, ChapterCardComponent,
|
||||
VolumeCardComponent, JsonPipe, AgeRatingPipe, DefaultValuePipe, ExternalRatingComponent, ReadMoreComponent, ReadTimePipe,
|
||||
RouterLink, TimeAgoPipe, AgeRatingImageComponent, CompactNumberPipe, IconAndTitleComponent, SafeHtmlPipe, BadgeExpanderComponent,
|
||||
A11yClickDirective, ReadTimeLeftPipe, PublicationStatusPipe, MetadataDetailRowComponent, DownloadButtonComponent, RelatedTabComponent, SeriesFormatComponent, MangaFormatPipe, CoverImageComponent]
|
||||
NgbNav, NgbNavItem, NgbNavLink, NgbNavContent, VirtualScrollerModule, SeriesCardComponent, ExternalSeriesCardComponent, NgbNavOutlet,
|
||||
TranslocoDirective, NgTemplateOutlet, NextExpectedCardComponent,
|
||||
NgClass, AsyncPipe, DetailsTabComponent, ChapterCardComponent,
|
||||
VolumeCardComponent, DefaultValuePipe, ExternalRatingComponent, ReadMoreComponent, RouterLink, BadgeExpanderComponent,
|
||||
PublicationStatusPipe, MetadataDetailRowComponent, DownloadButtonComponent, RelatedTabComponent, CoverImageComponent]
|
||||
})
|
||||
export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
||||
|
||||
@ -544,19 +517,6 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('document:keydown.shift', ['$event'])
|
||||
handleKeypress(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('document:keyup.shift', ['$event'])
|
||||
handleKeyUp(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
onNavChange(event: NgbNavChangeEvent) {
|
||||
this.bulkSelectionService.deselectAll();
|
||||
|
@ -108,22 +108,6 @@ export class CustomizeSidenavStreamsComponent implements OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@HostListener('document:keydown.shift', ['$event'])
|
||||
handleKeypress(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('document:keyup.shift', ['$event'])
|
||||
handleKeyUp(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = false;
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
|
||||
this.pageOperationsForm.get('accessibilityMode')?.valueChanges.pipe(
|
||||
|
@ -14,36 +14,40 @@
|
||||
<div [ngStyle]="{'height': ScrollingBlockHeight}" class="main-container container-fluid ps-0" #scrollingBlock>
|
||||
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
|
||||
|
||||
<app-card-detail-layout *ngIf="filter"
|
||||
[isLoading]="isLoading"
|
||||
[items]="series"
|
||||
[pagination]="pagination"
|
||||
[filterSettings]="filterSettings"
|
||||
[filterOpen]="filterOpen"
|
||||
[jumpBarKeys]="jumpbarKeys"
|
||||
[trackByIdentity]="trackByIdentity"
|
||||
[refresh]="refresh"
|
||||
(applyFilter)="updateFilter($event)">
|
||||
<ng-template #cardItem let-item let-position="idx">
|
||||
<app-series-card [series]="item" [libraryId]="item.libraryId" (reload)="removeSeries($event)"
|
||||
(selection)="bulkSelectionService.handleCardSelection('series', position, series.length, $event)"
|
||||
[selected]="bulkSelectionService.isCardSelected('series', position)" [allowSelection]="true"
|
||||
></app-series-card>
|
||||
</ng-template>
|
||||
@if (filter) {
|
||||
<app-card-detail-layout [isLoading]="isLoading"
|
||||
[items]="series"
|
||||
[pagination]="pagination"
|
||||
[filterSettings]="filterSettings"
|
||||
[filterOpen]="filterOpen"
|
||||
[jumpBarKeys]="jumpbarKeys"
|
||||
[trackByIdentity]="trackByIdentity"
|
||||
[refresh]="refresh"
|
||||
(applyFilter)="updateFilter($event)">
|
||||
<ng-template #cardItem let-item let-position="idx">
|
||||
<app-series-card [series]="item" [libraryId]="item.libraryId" (reload)="removeSeries($event)"
|
||||
(selection)="bulkSelectionService.handleCardSelection('series', position, series.length, $event)"
|
||||
[selected]="bulkSelectionService.isCardSelected('series', position)" [allowSelection]="true"
|
||||
></app-series-card>
|
||||
</ng-template>
|
||||
|
||||
<div *ngIf="!filterActive && series.length === 0">
|
||||
<ng-template #noData>
|
||||
{{t('no-items')}}
|
||||
</ng-template>
|
||||
@if (!filterActive && series.length === 0) {
|
||||
<div>
|
||||
<ng-template #noData>
|
||||
{{t('no-items')}}
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
<div *ngIf="filterActive && series.length === 0">
|
||||
<ng-template #noData>
|
||||
{{t('no-items-filtered')}}
|
||||
</ng-template>
|
||||
} @else if (filterActive && series.length === 0) {
|
||||
<div>
|
||||
<ng-template #noData>
|
||||
{{t('no-items-filtered')}}
|
||||
</ng-template>
|
||||
</div>
|
||||
}
|
||||
|
||||
</app-card-detail-layout>
|
||||
}
|
||||
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
@ -46,7 +46,7 @@ import {SeriesFilterV2} from "../../../_models/metadata/v2/series-filter-v2";
|
||||
styleUrls: ['./want-to-read.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [SideNavCompanionBarComponent, NgStyle, BulkOperationsComponent, CardDetailLayoutComponent, SeriesCardComponent, NgIf, DecimalPipe, TranslocoDirective]
|
||||
imports: [SideNavCompanionBarComponent, NgStyle, BulkOperationsComponent, CardDetailLayoutComponent, SeriesCardComponent, DecimalPipe, TranslocoDirective]
|
||||
})
|
||||
export class WantToReadComponent implements OnInit, AfterContentChecked {
|
||||
|
||||
@ -145,20 +145,6 @@ export class WantToReadComponent implements OnInit, AfterContentChecked {
|
||||
this.scrollService.setScrollContainer(this.scrollingBlock);
|
||||
}
|
||||
|
||||
@HostListener('document:keydown.shift', ['$event'])
|
||||
handleKeypress(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('document:keyup.shift', ['$event'])
|
||||
handleKeyUp(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
removeSeries(seriesId: number) {
|
||||
this.series = this.series.filter(s => s.id != seriesId);
|
||||
this.pagination.totalItems--;
|
||||
|
Loading…
x
Reference in New Issue
Block a user