diff --git a/API/Controllers/PersonController.cs b/API/Controllers/PersonController.cs index 593acc906..4e994cb37 100644 --- a/API/Controllers/PersonController.cs +++ b/API/Controllers/PersonController.cs @@ -90,6 +90,17 @@ public class PersonController : BaseApiController return Ok(list); } + // [HttpPost("all-v2")] + // public async Task>> GetAuthorsForBrowse(FilterV2Dto filter, [FromQuery] UserParams? userParams) + // { + // userParams ??= UserParams.Default; + // + // // var list = await _unitOfWork.PersonRepository.GetBrowsePersonDtos(User.GetUserId(), filter, userParams); + // // Response.AddPaginationHeader(list.CurrentPage, list.PageSize, list.TotalCount, list.TotalPages); + // + // return Ok([]); + // } + /// /// Updates the Person /// diff --git a/API/DTOs/Filtering/v2/FilterV2Dto.cs b/API/DTOs/Filtering/v2/FilterV2Dto.cs index 11dc42a6b..a247a17a6 100644 --- a/API/DTOs/Filtering/v2/FilterV2Dto.cs +++ b/API/DTOs/Filtering/v2/FilterV2Dto.cs @@ -16,7 +16,7 @@ public sealed record FilterV2Dto /// The name of the filter /// public string? Name { get; set; } - public ICollection Statements { get; set; } = new List(); + public ICollection Statements { get; set; } = []; public FilterCombination Combination { get; set; } = FilterCombination.And; public SortOptions? SortOptions { get; set; } diff --git a/API/Data/Repositories/SeriesRepository.cs b/API/Data/Repositories/SeriesRepository.cs index 28a0c431c..83678ecaf 100644 --- a/API/Data/Repositories/SeriesRepository.cs +++ b/API/Data/Repositories/SeriesRepository.cs @@ -1090,8 +1090,6 @@ public class SeriesRepository : ISeriesRepository return query.Where(s => false); } - - // First setup any FilterField.Libraries in the statements, as these don't have any traditional query statements applied here query = ApplyLibraryFilter(filter, query); diff --git a/UI/Web/src/app/_models/metadata/series-filter.ts b/UI/Web/src/app/_models/metadata/series-filter.ts index 19a2a7397..2cc9d2700 100644 --- a/UI/Web/src/app/_models/metadata/series-filter.ts +++ b/UI/Web/src/app/_models/metadata/series-filter.ts @@ -1,5 +1,5 @@ import {MangaFormat} from "../manga-format"; -import {SeriesFilterV2} from "./v2/series-filter-v2"; +import {FilterV2} from "./v2/filter-v2"; export interface FilterItem { title: string; @@ -51,7 +51,7 @@ export const mangaFormatFilters = [ ]; export interface FilterEvent { - filterV2: SeriesFilterV2; + filterV2: FilterV2; isFirst: boolean; } diff --git a/UI/Web/src/app/_models/metadata/v2/filter-statement.ts b/UI/Web/src/app/_models/metadata/v2/filter-statement.ts index d031927a2..f7d4768df 100644 --- a/UI/Web/src/app/_models/metadata/v2/filter-statement.ts +++ b/UI/Web/src/app/_models/metadata/v2/filter-statement.ts @@ -1,8 +1,7 @@ -import { FilterComparison } from "./filter-comparison"; -import { FilterField } from "./filter-field"; +import {FilterComparison} from "./filter-comparison"; -export interface FilterStatement { +export interface FilterStatement { comparison: FilterComparison; - field: FilterField; + field: T; value: string; -} \ No newline at end of file +} diff --git a/UI/Web/src/app/_models/metadata/v2/series-filter-v2.ts b/UI/Web/src/app/_models/metadata/v2/filter-v2.ts similarity index 77% rename from UI/Web/src/app/_models/metadata/v2/series-filter-v2.ts rename to UI/Web/src/app/_models/metadata/v2/filter-v2.ts index 4316a4caa..c95914b2f 100644 --- a/UI/Web/src/app/_models/metadata/v2/series-filter-v2.ts +++ b/UI/Web/src/app/_models/metadata/v2/filter-v2.ts @@ -2,9 +2,9 @@ import {FilterStatement} from "./filter-statement"; import {FilterCombination} from "./filter-combination"; import {SortOptions} from "./sort-options"; -export interface SeriesFilterV2 { +export interface FilterV2 { name?: string; - statements: Array; + statements: Array>; combination: FilterCombination; sortOptions?: SortOptions; limitTo: number; diff --git a/UI/Web/src/app/_models/metadata/v2/person-filter-field.ts b/UI/Web/src/app/_models/metadata/v2/person-filter-field.ts new file mode 100644 index 000000000..2a168983f --- /dev/null +++ b/UI/Web/src/app/_models/metadata/v2/person-filter-field.ts @@ -0,0 +1,5 @@ +export enum PersonFilterField { + None = -1, + Role = 1, + Name = 2 +} diff --git a/UI/Web/src/app/_services/filter.service.ts b/UI/Web/src/app/_services/filter.service.ts index e76c1926f..4d8079b3f 100644 --- a/UI/Web/src/app/_services/filter.service.ts +++ b/UI/Web/src/app/_services/filter.service.ts @@ -1,8 +1,7 @@ -import { Injectable } from '@angular/core'; -import {SeriesFilterV2} from "../_models/metadata/v2/series-filter-v2"; +import {Injectable} from '@angular/core'; +import {FilterV2} from "../_models/metadata/v2/filter-v2"; import {environment} from "../../environments/environment"; -import { HttpClient } from "@angular/common/http"; -import {JumpKey} from "../_models/jumpbar/jump-key"; +import {HttpClient} from "@angular/common/http"; import {SmartFilter} from "../_models/metadata/v2/smart-filter"; @Injectable({ @@ -13,7 +12,7 @@ export class FilterService { baseUrl = environment.apiUrl; constructor(private httpClient: HttpClient) { } - saveFilter(filter: SeriesFilterV2) { + saveFilter(filter: FilterV2) { return this.httpClient.post(this.baseUrl + 'filter/update', filter); } getAllFilters() { diff --git a/UI/Web/src/app/_services/metadata.service.ts b/UI/Web/src/app/_services/metadata.service.ts index 835fc85da..bb57808e5 100644 --- a/UI/Web/src/app/_services/metadata.service.ts +++ b/UI/Web/src/app/_services/metadata.service.ts @@ -13,7 +13,7 @@ import {FilterComparison} from '../_models/metadata/v2/filter-comparison'; import {FilterField} from '../_models/metadata/v2/filter-field'; import {mangaFormatFilters, SortField} from "../_models/metadata/series-filter"; import {FilterCombination} from "../_models/metadata/v2/filter-combination"; -import {SeriesFilterV2} from "../_models/metadata/v2/series-filter-v2"; +import {FilterV2} from "../_models/metadata/v2/filter-v2"; import {FilterStatement} from "../_models/metadata/v2/filter-statement"; import {SeriesDetailPlus} from "../_models/series-detail/series-detail-plus"; import {LibraryType} from "../_models/library/library"; @@ -148,9 +148,9 @@ export class MetadataService { return this.httpClient.get>(this.baseUrl + 'metadata/people-by-role?role=' + role); } - createDefaultFilterDto(): SeriesFilterV2 { + createDefaultFilterDto(): FilterV2 { return { - statements: [] as FilterStatement[], + statements: [] as FilterStatement[], combination: FilterCombination.And, limitTo: 0, sortOptions: { @@ -168,7 +168,7 @@ export class MetadataService { }; } - updateFilter(arr: Array, index: number, filterStmt: FilterStatement) { + updateFilter(arr: Array>, index: number, filterStmt: FilterStatement) { arr[index].comparison = filterStmt.comparison; arr[index].field = filterStmt.field; arr[index].value = filterStmt.value ? filterStmt.value + '' : ''; diff --git a/UI/Web/src/app/_services/reader.service.ts b/UI/Web/src/app/_services/reader.service.ts index 9941cd005..05958ee61 100644 --- a/UI/Web/src/app/_services/reader.service.ts +++ b/UI/Web/src/app/_services/reader.service.ts @@ -16,13 +16,14 @@ import {TextResonse} from '../_types/text-response'; import {AccountService} from './account.service'; import {takeUntilDestroyed} from "@angular/core/rxjs-interop"; import {PersonalToC} from "../_models/readers/personal-toc"; -import {SeriesFilterV2} from "../_models/metadata/v2/series-filter-v2"; +import {FilterV2} from "../_models/metadata/v2/filter-v2"; import NoSleep from 'nosleep.js'; import {FullProgress} from "../_models/readers/full-progress"; import {Volume} from "../_models/volume"; import {UtilityService} from "../shared/_services/utility.service"; import {translate} from "@jsverse/transloco"; import {ToastrService} from "ngx-toastr"; +import {FilterField} from "../_models/metadata/v2/filter-field"; export const CHAPTER_ID_DOESNT_EXIST = -1; @@ -107,7 +108,7 @@ export class ReaderService { return this.httpClient.post(this.baseUrl + 'reader/unbookmark', {seriesId, volumeId, chapterId, page}); } - getAllBookmarks(filter: SeriesFilterV2 | undefined) { + getAllBookmarks(filter: FilterV2 | undefined) { return this.httpClient.post(this.baseUrl + 'reader/all-bookmarks', filter); } diff --git a/UI/Web/src/app/_services/series.service.ts b/UI/Web/src/app/_services/series.service.ts index b440b1eb7..c5642cbc3 100644 --- a/UI/Web/src/app/_services/series.service.ts +++ b/UI/Web/src/app/_services/series.service.ts @@ -1,28 +1,26 @@ -import { HttpClient, HttpParams } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; -import { environment } from 'src/environments/environment'; -import { UtilityService } from '../shared/_services/utility.service'; -import { Chapter } from '../_models/chapter'; -import { PaginatedResult } from '../_models/pagination'; -import { Series } from '../_models/series'; -import { RelatedSeries } from '../_models/series-detail/related-series'; -import { SeriesDetail } from '../_models/series-detail/series-detail'; -import { SeriesGroup } from '../_models/series-group'; -import { SeriesMetadata } from '../_models/metadata/series-metadata'; -import { Volume } from '../_models/volume'; -import { ImageService } from './image.service'; -import { TextResonse } from '../_types/text-response'; -import { SeriesFilterV2 } from '../_models/metadata/v2/series-filter-v2'; -import {UserReview} from "../_single-module/review-card/user-review"; +import {HttpClient, HttpParams} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {Observable} from 'rxjs'; +import {map} from 'rxjs/operators'; +import {environment} from 'src/environments/environment'; +import {UtilityService} from '../shared/_services/utility.service'; +import {Chapter} from '../_models/chapter'; +import {PaginatedResult} from '../_models/pagination'; +import {Series} from '../_models/series'; +import {RelatedSeries} from '../_models/series-detail/related-series'; +import {SeriesDetail} from '../_models/series-detail/series-detail'; +import {SeriesGroup} from '../_models/series-group'; +import {SeriesMetadata} from '../_models/metadata/series-metadata'; +import {Volume} from '../_models/volume'; +import {TextResonse} from '../_types/text-response'; +import {FilterV2} from '../_models/metadata/v2/filter-v2'; import {Rating} from "../_models/rating"; import {Recommendation} from "../_models/series-detail/recommendation"; import {ExternalSeriesDetail} from "../_models/series-detail/external-series-detail"; import {NextExpectedChapter} from "../_models/series-detail/next-expected-chapter"; import {QueryContext} from "../_models/metadata/v2/query-context"; -import {ExternalSeries} from "../_models/series-detail/external-series"; import {ExternalSeriesMatch} from "../_models/series-detail/external-series-match"; +import {FilterField} from "../_models/metadata/v2/filter-field"; @Injectable({ providedIn: 'root' @@ -33,10 +31,9 @@ export class SeriesService { paginatedResults: PaginatedResult = new PaginatedResult(); paginatedSeriesForTagsResults: PaginatedResult = new PaginatedResult(); - constructor(private httpClient: HttpClient, private imageService: ImageService, - private utilityService: UtilityService) { } + constructor(private httpClient: HttpClient, private utilityService: UtilityService) { } - getAllSeriesV2(pageNum?: number, itemsPerPage?: number, filter?: SeriesFilterV2, context: QueryContext = QueryContext.None) { + getAllSeriesV2(pageNum?: number, itemsPerPage?: number, filter?: FilterV2, context: QueryContext = QueryContext.None) { let params = new HttpParams(); params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage); const data = filter || {}; @@ -48,7 +45,7 @@ export class SeriesService { ); } - getSeriesForLibraryV2(pageNum?: number, itemsPerPage?: number, filter?: SeriesFilterV2) { + getSeriesForLibraryV2(pageNum?: number, itemsPerPage?: number, filter?: FilterV2) { let params = new HttpParams(); params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage); const data = filter || {}; @@ -100,7 +97,7 @@ export class SeriesService { return this.httpClient.post(this.baseUrl + 'reader/mark-unread', {seriesId}); } - getRecentlyAdded(pageNum?: number, itemsPerPage?: number, filter?: SeriesFilterV2) { + getRecentlyAdded(pageNum?: number, itemsPerPage?: number, filter?: FilterV2) { let params = new HttpParams(); params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage); @@ -116,7 +113,7 @@ export class SeriesService { return this.httpClient.post(this.baseUrl + 'series/recently-updated-series', {}); } - getWantToRead(pageNum?: number, itemsPerPage?: number, filter?: SeriesFilterV2): Observable> { + getWantToRead(pageNum?: number, itemsPerPage?: number, filter?: FilterV2): Observable> { let params = new HttpParams(); params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage); const data = filter || {}; @@ -134,7 +131,7 @@ export class SeriesService { })); } - getOnDeck(libraryId: number = 0, pageNum?: number, itemsPerPage?: number, filter?: SeriesFilterV2) { + getOnDeck(libraryId: number = 0, pageNum?: number, itemsPerPage?: number, filter?: FilterV2) { let params = new HttpParams(); params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage); const data = filter || {}; diff --git a/UI/Web/src/app/all-series/_components/all-series/all-series.component.html b/UI/Web/src/app/all-series/_components/all-series/all-series.component.html index 2c23fd37c..d573b0eb7 100644 --- a/UI/Web/src/app/all-series/_components/all-series/all-series.component.html +++ b/UI/Web/src/app/all-series/_components/all-series/all-series.component.html @@ -13,10 +13,10 @@ diff --git a/UI/Web/src/app/all-series/_components/all-series/all-series.component.ts b/UI/Web/src/app/all-series/_components/all-series/all-series.component.ts index 453ff1c31..81afdf88e 100644 --- a/UI/Web/src/app/all-series/_components/all-series/all-series.component.ts +++ b/UI/Web/src/app/all-series/_components/all-series/all-series.component.ts @@ -32,11 +32,12 @@ import { SideNavCompanionBarComponent } from '../../../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component'; import {translate, TranslocoDirective} from "@jsverse/transloco"; -import {SeriesFilterV2} from "../../../_models/metadata/v2/series-filter-v2"; +import {FilterV2} from "../../../_models/metadata/v2/filter-v2"; import {FilterComparison} from "../../../_models/metadata/v2/filter-comparison"; import {BrowseTitlePipe} from "../../../_pipes/browse-title.pipe"; import {MetadataService} from "../../../_services/metadata.service"; import {Observable} from "rxjs"; +import {FilterField} from "../../../_models/metadata/v2/filter-field"; @Component({ @@ -67,10 +68,10 @@ export class AllSeriesComponent implements OnInit { series: Series[] = []; loadingSeries = false; pagination: Pagination = new Pagination(); - filter: SeriesFilterV2 | undefined = undefined; - filterSettings: FilterSettings = new FilterSettings(); + filter: FilterV2 | undefined = undefined; + filterSettings: FilterSettings = new FilterSettings(); filterOpen: EventEmitter = new EventEmitter(); - filterActiveCheck!: SeriesFilterV2; + filterActiveCheck!: FilterV2; filterActive: boolean = false; jumpbarKeys: Array = []; browseTitlePipe = new BrowseTitlePipe(); @@ -132,12 +133,12 @@ export class AllSeriesComponent implements OnInit { this.filterUtilityService.filterPresetsFromUrl(this.route.snapshot).subscribe(filter => { this.filter = filter; - this.title = this.route.snapshot.queryParamMap.get('title') || this.filter.name || this.title; + this.title = this.route.snapshot.queryParamMap.get('title') || this.filter!.name || this.title; this.titleService.setTitle('Kavita - ' + this.title); // To provide a richer experience, when we are browsing just a Genre/Tag/etc, we regenerate the title (if not explicitly passed) to "Browse {GenreName}" if (this.shouldRewriteTitle()) { - const field = this.filter.statements[0].field; + const field = this.filter!.statements[0].field; // This api returns value as string and number, it will complain without the casting (this.metadataService.getOptionsForFilterField(field) as Observable).subscribe((opts: any[]) => { diff --git a/UI/Web/src/app/bookmark/_components/bookmarks/bookmarks.component.ts b/UI/Web/src/app/bookmark/_components/bookmarks/bookmarks.component.ts index f3b638ce9..a37658ca6 100644 --- a/UI/Web/src/app/bookmark/_components/bookmarks/bookmarks.component.ts +++ b/UI/Web/src/app/bookmark/_components/bookmarks/bookmarks.component.ts @@ -24,9 +24,10 @@ import { SideNavCompanionBarComponent } from '../../../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component'; import {translate, TranslocoDirective, TranslocoService} from "@jsverse/transloco"; -import {SeriesFilterV2} from "../../../_models/metadata/v2/series-filter-v2"; +import {FilterV2} from "../../../_models/metadata/v2/filter-v2"; import {Title} from "@angular/platform-browser"; import {WikiLink} from "../../../_models/wiki"; +import {FilterField} from "../../../_models/metadata/v2/filter-field"; @Component({ selector: 'app-bookmarks', @@ -63,11 +64,11 @@ export class BookmarksComponent implements OnInit { jumpbarKeys: Array = []; pagination: Pagination = new Pagination(); - filter: SeriesFilterV2 | undefined = undefined; - filterSettings: FilterSettings = new FilterSettings(); + filter: FilterV2 | undefined = undefined; + filterSettings: FilterSettings = new FilterSettings(); filterOpen: EventEmitter = new EventEmitter(); filterActive: boolean = false; - filterActiveCheck!: SeriesFilterV2; + filterActiveCheck!: FilterV2; trackByIdentity = (index: number, item: Series) => `${item.name}_${item.localizedName}_${item.pagesRead}`; refresh: EventEmitter = new EventEmitter(); diff --git a/UI/Web/src/app/browse/browse-people/browse-authors.component.html b/UI/Web/src/app/browse/browse-people/browse-authors.component.html index 20d280e16..bd6f18e2d 100644 --- a/UI/Web/src/app/browse/browse-people/browse-authors.component.html +++ b/UI/Web/src/app/browse/browse-people/browse-authors.component.html @@ -1,6 +1,6 @@
- +

{{t('title')}}

@@ -55,6 +55,8 @@ [filteringDisabled]="true" [customSort]="filterGroup.get('sortField')!.value !== PersonSortField.Name" [refresh]="refresh" + [filterSettings]="filterSettings" + [filterOpen]="filterOpen" > diff --git a/UI/Web/src/app/browse/browse-people/browse-authors.component.ts b/UI/Web/src/app/browse/browse-people/browse-authors.component.ts index be8d6c86f..3580fdcba 100644 --- a/UI/Web/src/app/browse/browse-people/browse-authors.component.ts +++ b/UI/Web/src/app/browse/browse-people/browse-authors.component.ts @@ -15,7 +15,7 @@ import {DecimalPipe} from "@angular/common"; import {Series} from "../../_models/series"; import {Pagination} from "../../_models/pagination"; import {JumpKey} from "../../_models/jumpbar/jump-key"; -import {Router} from "@angular/router"; +import {ActivatedRoute, Router} from "@angular/router"; import {PersonService} from "../../_services/person.service"; import {BrowsePerson} from "../../_models/metadata/browse/browse-person"; import {JumpbarService} from "../../_services/jumpbar.service"; @@ -32,6 +32,10 @@ import {debounceTime, tap} from "rxjs/operators"; import {SortButtonComponent} from "../../_single-module/sort-button/sort-button.component"; import {PersonSortField} from "../../_models/metadata/v2/person-sort-field"; import {PersonSortOptions} from "../../_models/metadata/v2/sort-options"; +import {FilterSettings} from "../../metadata-filter/filter-settings"; +import {PersonFilterField} from "../../_models/metadata/v2/person-filter-field"; +import {FilterUtilitiesService} from "../../shared/_services/filter-utilities.service"; +import {FilterV2} from "../../_models/metadata/v2/filter-v2"; @Component({ @@ -59,6 +63,8 @@ export class BrowseAuthorsComponent implements OnInit { private readonly router = inject(Router); private readonly personService = inject(PersonService); private readonly jumpbarService = inject(JumpbarService); + private readonly route = inject(ActivatedRoute); + private readonly filterUtilityService = inject(FilterUtilitiesService); protected readonly imageService = inject(ImageService); @@ -77,12 +83,30 @@ export class BrowseAuthorsComponent implements OnInit { query: new FormControl('', []), }); isAscending: boolean = true; + filterSettings: FilterSettings = new FilterSettings(); + filterActive: boolean = false; + filterOpen: EventEmitter = new EventEmitter(); + filter: FilterV2 | undefined = undefined; + filterActiveCheck!: FilterV2; ngOnInit() { this.isLoading = true; this.cdRef.markForCheck(); + + this.filterUtilityService.filterPresetsFromUrl(this.route.snapshot).subscribe(filter => { + this.filter = filter; + + this.filterActiveCheck = this.filterUtilityService.createPersonV2Filter(); + this.filterActiveCheck!.statements.push(this.filterUtilityService.createPersonV2DefaultStatement()); + this.filterSettings.presetsV2 = this.filter; + + this.cdRef.markForCheck(); + }); + + + this.filterGroup.valueChanges.pipe( takeUntilDestroyed(this.destroyRef), debounceTime(200), diff --git a/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.html b/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.html index 1981efdab..c58b57fcd 100644 --- a/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.html +++ b/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.html @@ -12,7 +12,7 @@ } - {{header}}  + {{header}}  @if (pagination) { {{pagination.totalItems}} @@ -25,6 +25,7 @@ } +
@@ -34,13 +35,14 @@
-
- -
+ @for (item of scroll.viewPortItems; track trackByIdentity(i, item); let i = $index) { +
+ +
+ }
diff --git a/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.ts b/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.ts index 8d59dfbfc..d62c5b28f 100644 --- a/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.ts +++ b/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.ts @@ -35,14 +35,27 @@ import {LoadingComponent} from "../../shared/loading/loading.component"; import {MetadataFilterComponent} from "../../metadata-filter/metadata-filter.component"; import {TranslocoDirective} from "@jsverse/transloco"; import {CardActionablesComponent} from "../../_single-module/card-actionables/card-actionables.component"; -import {SeriesFilterV2} from "../../_models/metadata/v2/series-filter-v2"; import {filter, map} from "rxjs/operators"; import {takeUntilDestroyed} from "@angular/core/rxjs-interop"; import {tap} from "rxjs"; +import {FilterV2} from "../../_models/metadata/v2/filter-v2"; const ANIMATION_TIME_MS = 0; +/** + * Provides a virtualized card layout, jump bar, and metadata filter bar. + * + * How to use: + * - For filtering: + * - pass a filterSettings which will bootstrap the filtering bar + * - pass a jumpbar method binding to calc the count for the entity + * - For card layout + * - Pass an identity function for trackby + * - Pass a pagination object for the total count + * - Pass the items + * - + */ @Component({ selector: 'app-card-detail-layout', imports: [LoadingComponent, VirtualScrollerModule, CardActionablesComponent, MetadataFilterComponent, @@ -85,8 +98,12 @@ export class CardDetailLayoutComponent implements OnInit, OnChanges { * A trackBy to help with rendering. This is required as without it there are issues when scrolling */ @Input({required: true}) trackByIdentity!: TrackByFunction; - @Input() filterSettings!: FilterSettings; + @Input() filterSettings!: FilterSettings; @Input() refresh!: EventEmitter; + /** + * Pass the filter object optionally. If not passed, will create a SeriesFilter by default + */ + filter: FilterV2 | undefined = undefined; /** * Will force the jumpbar to be disabled - in cases where you're not using a traditional filter config @@ -104,7 +121,6 @@ export class CardDetailLayoutComponent implements OnInit, OnChanges { @ViewChild(VirtualScrollerComponent) private virtualScroller!: VirtualScrollerComponent; - filter: SeriesFilterV2 = this.filterUtilityService.createSeriesV2Filter(); libraries: Array> = []; updateApplied: number = 0; @@ -128,6 +144,10 @@ export class CardDetailLayoutComponent implements OnInit, OnChanges { if (this.trackByIdentity === undefined) { this.trackByIdentity = (_: number, item: any) => `${this.header}_${this.updateApplied}_${item?.libraryId}`; } + // This shouldn't be needed as filter is a temp variable to check if a custom sort is present + // if (!this.filter) { + // this.filter = this.filterUtilityService.createSeriesV2Filter(); + // } if (this.filterSettings === undefined) { this.filterSettings = new FilterSettings(); @@ -177,7 +197,7 @@ export class CardDetailLayoutComponent implements OnInit, OnChanges { hasCustomSort() { if (this.customSort) return true; if (this.filteringDisabled) return false; - + return this.filter?.sortOptions?.sortField != SortField.SortName || !this.filter?.sortOptions.isAscending; } diff --git a/UI/Web/src/app/collections/_components/collection-detail/collection-detail.component.ts b/UI/Web/src/app/collections/_components/collection-detail/collection-detail.component.ts index d99626b64..2a5b50123 100644 --- a/UI/Web/src/app/collections/_components/collection-detail/collection-detail.component.ts +++ b/UI/Web/src/app/collections/_components/collection-detail/collection-detail.component.ts @@ -50,7 +50,7 @@ import {translate, TranslocoDirective, TranslocoService} from "@jsverse/transloc import {CardActionablesComponent} from "../../../_single-module/card-actionables/card-actionables.component"; import {FilterField} from "../../../_models/metadata/v2/filter-field"; import {FilterComparison} from "../../../_models/metadata/v2/filter-comparison"; -import {SeriesFilterV2} from "../../../_models/metadata/v2/series-filter-v2"; +import {FilterV2} from "../../../_models/metadata/v2/filter-v2"; import {AccountService} from "../../../_services/account.service"; import {User} from "../../../_models/user"; import {ScrobbleProvider} from "../../../_services/scrobbling.service"; @@ -62,6 +62,7 @@ import { import {DefaultModalOptions} from "../../../_models/default-modal-options"; import {ScrobbleProviderNamePipe} from "../../../_pipes/scrobble-provider-name.pipe"; import {PromotedIconComponent} from "../../../shared/_components/promoted-icon/promoted-icon.component"; +import {FilterStatement} from "../../../_models/metadata/v2/filter-statement"; @Component({ selector: 'app-collection-detail', @@ -109,13 +110,13 @@ export class CollectionDetailComponent implements OnInit, AfterContentChecked { series: Array = []; pagination: Pagination = new Pagination(); collectionTagActions: ActionItem[] = []; - filter: SeriesFilterV2 | undefined = undefined; - filterSettings: FilterSettings = new FilterSettings(); + filter: FilterV2 | undefined = undefined; + filterSettings: FilterSettings = new FilterSettings(); summary: string = ''; user!: User; actionInProgress: boolean = false; - filterActiveCheck!: SeriesFilterV2; + filterActiveCheck!: FilterV2; filterActive: boolean = false; jumpbarKeys: Array = []; @@ -189,9 +190,9 @@ export class CollectionDetailComponent implements OnInit, AfterContentChecked { const tagId = parseInt(routeId, 10); this.filterUtilityService.filterPresetsFromUrl(this.route.snapshot).subscribe(filter => { - this.filter = filter; + this.filter = filter as FilterV2; - if (this.filter.statements.filter(stmt => stmt.field === FilterField.CollectionTags).length === 0) { + if (this.filter.statements.filter((stmt: FilterStatement) => stmt.field === FilterField.CollectionTags).length === 0) { this.filter!.statements.push({field: FilterField.CollectionTags, value: tagId + '', comparison: FilterComparison.Equal}); } this.filterActiveCheck = this.filterUtilityService.createSeriesV2Filter(); diff --git a/UI/Web/src/app/library-detail/library-detail.component.ts b/UI/Web/src/app/library-detail/library-detail.component.ts index b2563a1a6..cc0ca53fa 100644 --- a/UI/Web/src/app/library-detail/library-detail.component.ts +++ b/UI/Web/src/app/library-detail/library-detail.component.ts @@ -37,7 +37,7 @@ import { SideNavCompanionBarComponent } from '../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component'; import {TranslocoDirective} from "@jsverse/transloco"; -import {SeriesFilterV2} from "../_models/metadata/v2/series-filter-v2"; +import {FilterV2} from "../_models/metadata/v2/filter-v2"; import {FilterComparison} from "../_models/metadata/v2/filter-comparison"; import {FilterField} from "../_models/metadata/v2/filter-field"; import {CardActionablesComponent} from "../_single-module/card-actionables/card-actionables.component"; @@ -75,11 +75,11 @@ export class LibraryDetailComponent implements OnInit { loadingSeries = false; pagination: Pagination = {currentPage: 0, totalPages: 0, totalItems: 0, itemsPerPage: 0}; actions: ActionItem[] = []; - filter: SeriesFilterV2 | undefined = undefined; - filterSettings: FilterSettings = new FilterSettings(); + filter: FilterV2 | undefined = undefined; + filterSettings: FilterSettings = new FilterSettings(); filterOpen: EventEmitter = new EventEmitter(); filterActive: boolean = false; - filterActiveCheck!: SeriesFilterV2; + filterActiveCheck!: FilterV2; refresh: EventEmitter = new EventEmitter(); jumpKeys: Array = []; bulkLoader: boolean = false; @@ -185,7 +185,7 @@ export class LibraryDetailComponent implements OnInit { this.actions = this.actionFactoryService.getLibraryActions(this.handleAction.bind(this)); this.filterUtilityService.filterPresetsFromUrl(this.route.snapshot).subscribe(filter => { - this.filter = filter; + this.filter = filter as FilterV2; if (this.filter.statements.filter(stmt => stmt.field === FilterField.Libraries).length === 0) { this.filter!.statements.push({field: FilterField.Libraries, value: this.libraryId + '', comparison: FilterComparison.Equal}); diff --git a/UI/Web/src/app/metadata-filter/_components/metadata-builder/metadata-builder.component.ts b/UI/Web/src/app/metadata-filter/_components/metadata-builder/metadata-builder.component.ts index 8586d66e5..d0bbc6e2e 100644 --- a/UI/Web/src/app/metadata-filter/_components/metadata-builder/metadata-builder.component.ts +++ b/UI/Web/src/app/metadata-filter/_components/metadata-builder/metadata-builder.component.ts @@ -11,7 +11,7 @@ import { } from '@angular/core'; import {MetadataService} from 'src/app/_services/metadata.service'; import {Breakpoint, UtilityService} from 'src/app/shared/_services/utility.service'; -import {SeriesFilterV2} from 'src/app/_models/metadata/v2/series-filter-v2'; +import {FilterV2} from 'src/app/_models/metadata/v2/filter-v2'; import {MetadataFilterRowComponent} from "../metadata-filter-row/metadata-filter-row.component"; import {FilterStatement} from "../../../_models/metadata/v2/filter-statement"; import {FormControl, FormGroup, FormsModule, ReactiveFormsModule} from "@angular/forms"; @@ -38,13 +38,13 @@ import {translate, TranslocoDirective} from "@jsverse/transloco"; }) export class MetadataBuilderComponent implements OnInit { - @Input({required: true}) filter!: SeriesFilterV2; + @Input({required: true}) filter!: FilterV2; /** * The number of statements that can be. 0 means unlimited. -1 means none. */ @Input() statementLimit = 0; @Input() availableFilterFields = allFields; - @Output() update: EventEmitter = new EventEmitter(); + @Output() update: EventEmitter> = new EventEmitter>(); @Output() apply: EventEmitter = new EventEmitter(); private readonly cdRef = inject(ChangeDetectorRef); @@ -79,7 +79,7 @@ export class MetadataBuilderComponent implements OnInit { this.cdRef.markForCheck(); } - updateFilter(index: number, filterStmt: FilterStatement) { + updateFilter(index: number, filterStmt: FilterStatement) { this.metadataService.updateFilter(this.filter.statements, index, filterStmt); this.update.emit(this.filter); } diff --git a/UI/Web/src/app/metadata-filter/_components/metadata-filter-row/metadata-filter-row.component.ts b/UI/Web/src/app/metadata-filter/_components/metadata-filter-row/metadata-filter-row.component.ts index b0dbf0608..71a9a65b8 100644 --- a/UI/Web/src/app/metadata-filter/_components/metadata-filter-row/metadata-filter-row.component.ts +++ b/UI/Web/src/app/metadata-filter/_components/metadata-filter-row/metadata-filter-row.component.ts @@ -13,8 +13,6 @@ import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms'; import {FilterStatement} from '../../../_models/metadata/v2/filter-statement'; import {BehaviorSubject, distinctUntilChanged, filter, Observable, of, startWith, switchMap, tap} from 'rxjs'; import {MetadataService} from 'src/app/_services/metadata.service'; -import {LibraryService} from 'src/app/_services/library.service'; -import {CollectionTagService} from 'src/app/_services/collection-tag.service'; import {FilterComparison} from 'src/app/_models/metadata/v2/filter-comparison'; import {allFields, FilterField} from 'src/app/_models/metadata/v2/filter-field'; import {AsyncPipe} from "@angular/common"; @@ -142,8 +140,6 @@ export class MetadataFilterRowComponent implements OnInit { private readonly destroyRef = inject(DestroyRef); private readonly dateParser = inject(NgbDateParserFormatter); private readonly metadataService = inject(MetadataService); - private readonly libraryService = inject(LibraryService); - private readonly collectionTagService = inject(CollectionTagService); private readonly translocoService = inject(TranslocoService); @@ -151,9 +147,9 @@ export class MetadataFilterRowComponent implements OnInit { /** * Slightly misleading as this is the initial state and will be updated on the filterStatement event emitter */ - @Input() preset!: FilterStatement; + @Input() preset!: FilterStatement; @Input() availableFields: Array = allFields; - @Output() filterStatement = new EventEmitter(); + @Output() filterStatement = new EventEmitter>(); formGroup: FormGroup = new FormGroup({ diff --git a/UI/Web/src/app/metadata-filter/filter-settings.ts b/UI/Web/src/app/metadata-filter/filter-settings.ts index 452abee71..4f9e91b71 100644 --- a/UI/Web/src/app/metadata-filter/filter-settings.ts +++ b/UI/Web/src/app/metadata-filter/filter-settings.ts @@ -1,8 +1,8 @@ -import { SeriesFilterV2 } from "../_models/metadata/v2/series-filter-v2"; +import {FilterV2} from "../_models/metadata/v2/filter-v2"; -export class FilterSettings { +export class FilterSettings { + presetsV2: FilterV2 | undefined; sortDisabled = false; - presetsV2: SeriesFilterV2 | undefined; /** * The number of statements that can be on the filter. Set to 1 to disable adding more. */ diff --git a/UI/Web/src/app/metadata-filter/metadata-filter.component.ts b/UI/Web/src/app/metadata-filter/metadata-filter.component.ts index 347efe088..32788d424 100644 --- a/UI/Web/src/app/metadata-filter/metadata-filter.component.ts +++ b/UI/Web/src/app/metadata-filter/metadata-filter.component.ts @@ -17,14 +17,14 @@ import {Library} from '../_models/library/library'; import {allSortFields, FilterEvent, FilterItem, SortField} from '../_models/metadata/series-filter'; import {ToggleService} from '../_services/toggle.service'; import {FilterSettings} from './filter-settings'; -import {SeriesFilterV2} from '../_models/metadata/v2/series-filter-v2'; +import {FilterV2} from '../_models/metadata/v2/filter-v2'; import {takeUntilDestroyed} from "@angular/core/rxjs-interop"; import {DrawerComponent} from '../shared/drawer/drawer.component'; import {AsyncPipe, NgClass, NgTemplateOutlet} from '@angular/common'; import {translate, TranslocoModule, TranslocoService} from "@jsverse/transloco"; import {SortFieldPipe} from "../_pipes/sort-field.pipe"; import {MetadataBuilderComponent} from "./_components/metadata-builder/metadata-builder.component"; -import {allFields} from "../_models/metadata/v2/filter-field"; +import {allFields, FilterField} from "../_models/metadata/v2/filter-field"; import {FilterService} from "../_services/filter.service"; import {ToastrService} from "ngx-toastr"; import {animate, style, transition, trigger} from "@angular/animations"; @@ -52,6 +52,7 @@ import {SortButtonComponent} from "../_single-module/sort-button/sort-button.com MetadataBuilderComponent, NgClass, SortButtonComponent] }) export class MetadataFilterComponent implements OnInit { + protected readonly allFilterFields = allFields; private readonly destroyRef = inject(DestroyRef); public readonly utilityService = inject(UtilityService); @@ -65,7 +66,7 @@ export class MetadataFilterComponent implements OnInit { protected readonly allSortFields = allSortFields.map(f => { return {title: this.sortFieldPipe.transform(f), value: f}; }).sort((a, b) => a.title.localeCompare(b.title)); - protected readonly allFilterFields = allFields; + /** * This toggles the opening/collapsing of the metadata filter code @@ -75,7 +76,7 @@ export class MetadataFilterComponent implements OnInit { * Should filtering be shown on the page */ @Input() filteringDisabled: boolean = false; - @Input({required: true}) filterSettings!: FilterSettings; + @Input({required: true}) filterSettings!: FilterSettings; @Output() applyFilter: EventEmitter = new EventEmitter(); @ContentChild('[ngbCollapse]') collapse!: NgbCollapse; @@ -92,7 +93,7 @@ export class MetadataFilterComponent implements OnInit { updateApplied: number = 0; fullyLoaded: boolean = false; - filterV2: SeriesFilterV2 | undefined; + filterV2: FilterV2 | undefined; @@ -148,7 +149,7 @@ export class MetadataFilterComponent implements OnInit { return clonedObj; } - handleFilters(filter: SeriesFilterV2) { + handleFilters(filter: FilterV2) { this.filterV2 = filter; } diff --git a/UI/Web/src/app/nav/_components/nav-header/nav-header.component.ts b/UI/Web/src/app/nav/_components/nav-header/nav-header.component.ts index 980a1be55..27bfefd85 100644 --- a/UI/Web/src/app/nav/_components/nav-header/nav-header.component.ts +++ b/UI/Web/src/app/nav/_components/nav-header/nav-header.component.ts @@ -159,7 +159,7 @@ export class NavHeaderComponent implements OnInit { }); } - goTo(statement: FilterStatement) { + goTo(statement: FilterStatement) { let params: any = {}; const filter = this.filterUtilityService.createSeriesV2Filter(); filter.statements = [statement]; diff --git a/UI/Web/src/app/person-detail/person-detail.component.ts b/UI/Web/src/app/person-detail/person-detail.component.ts index 31b7f976b..524be9de4 100644 --- a/UI/Web/src/app/person-detail/person-detail.component.ts +++ b/UI/Web/src/app/person-detail/person-detail.component.ts @@ -23,7 +23,7 @@ import {PersonRolePipe} from "../_pipes/person-role.pipe"; import {CarouselReelComponent} from "../carousel/_components/carousel-reel/carousel-reel.component"; import {FilterComparison} from "../_models/metadata/v2/filter-comparison"; import {FilterUtilitiesService} from "../shared/_services/filter-utilities.service"; -import {SeriesFilterV2} from "../_models/metadata/v2/series-filter-v2"; +import {FilterV2} from "../_models/metadata/v2/filter-v2"; import {allPeople, FilterField, personRoleForFilterField} from "../_models/metadata/v2/filter-field"; import {Series} from "../_models/series"; import {takeUntilDestroyed} from "@angular/core/rxjs-interop"; @@ -98,7 +98,7 @@ export class PersonDetailComponent implements OnInit { roles$: Observable | null = null; roles: PersonRole[] | null = null; works$: Observable | null = null; - filter: SeriesFilterV2 | null = null; + filter: FilterV2 | null = null; personActions: Array> = this.actionService.getPersonActions(this.handleAction.bind(this)); chaptersByRole: any = {}; anilistUrl: string = ''; @@ -181,7 +181,7 @@ export class PersonDetailComponent implements OnInit { } createFilter(roles: PersonRole[]) { - const filter: SeriesFilterV2 = this.filterUtilityService.createSeriesV2Filter(); + const filter = this.filterUtilityService.createSeriesV2Filter(); filter.combination = FilterCombination.Or; filter.limitTo = 20; diff --git a/UI/Web/src/app/shared/_services/filter-utilities.service.ts b/UI/Web/src/app/shared/_services/filter-utilities.service.ts index a994340f1..fceeedeed 100644 --- a/UI/Web/src/app/shared/_services/filter-utilities.service.ts +++ b/UI/Web/src/app/shared/_services/filter-utilities.service.ts @@ -2,7 +2,7 @@ import {inject, Injectable} from '@angular/core'; import {ActivatedRouteSnapshot, Params, Router} from '@angular/router'; import {SortField} from 'src/app/_models/metadata/series-filter'; import {MetadataService} from "../../_services/metadata.service"; -import {SeriesFilterV2} from "../../_models/metadata/v2/series-filter-v2"; +import {FilterV2} from "../../_models/metadata/v2/filter-v2"; import {FilterStatement} from "../../_models/metadata/v2/filter-statement"; import {FilterCombination} from "../../_models/metadata/v2/filter-combination"; import {FilterField} from "../../_models/metadata/v2/filter-field"; @@ -11,8 +11,9 @@ import {HttpClient} from "@angular/common/http"; import {TextResonse} from "../../_types/text-response"; import {environment} from "../../../environments/environment"; import {map, tap} from "rxjs/operators"; -import {of, switchMap} from "rxjs"; +import {Observable, of, switchMap} from "rxjs"; import {Location} from "@angular/common"; +import {PersonFilterField} from "../../_models/metadata/v2/person-filter-field"; @Injectable({ @@ -27,12 +28,12 @@ export class FilterUtilitiesService { private apiUrl = environment.apiUrl; - encodeFilter(filter: SeriesFilterV2 | undefined) { + encodeFilter(filter: FilterV2 | undefined) { return this.http.post(this.apiUrl + 'filter/encode', filter, TextResonse); } decodeFilter(encodedFilter: string) { - return this.http.post(this.apiUrl + 'filter/decode', {encodedFilter}).pipe(map(filter => { + return this.http.post>(this.apiUrl + 'filter/decode', {encodedFilter}).pipe(map(filter => { if (filter == null) { filter = this.metadataService.createDefaultFilterDto(); filter.statements.push(this.createSeriesV2DefaultStatement()); @@ -42,13 +43,13 @@ export class FilterUtilitiesService { })) } - updateUrlFromFilter(filter: SeriesFilterV2 | undefined) { + updateUrlFromFilter(filter: FilterV2 | undefined) { return this.encodeFilter(filter).pipe(tap(encodedFilter => { window.history.replaceState(window.location.href, '', window.location.href.split('?')[0]+ '?' + encodedFilter); })); } - filterPresetsFromUrl(snapshot: ActivatedRouteSnapshot) { + filterPresetsFromUrl(snapshot: ActivatedRouteSnapshot): Observable> { const filter = this.metadataService.createDefaultFilterDto(); filter.statements.push(this.createSeriesV2DefaultStatement()); if (!window.location.href.includes('?')) return of(filter); @@ -72,7 +73,7 @@ export class FilterUtilitiesService { })); } - applyFilterWithParams(page: Array, filter: SeriesFilterV2, extraParams: Params) { + applyFilterWithParams(page: Array, filter: FilterV2, extraParams: Params) { return this.encodeFilter(filter).pipe(switchMap(encodedFilter => { let url = page.join('/') + '?' + encodedFilter; url += Object.keys(extraParams).map(k => `&${k}=${extraParams[k]}`).join(''); @@ -81,7 +82,7 @@ export class FilterUtilitiesService { })); } - createSeriesV2Filter(): SeriesFilterV2 { + createSeriesV2Filter(): FilterV2 { return { combination: FilterCombination.And, statements: [], @@ -93,11 +94,31 @@ export class FilterUtilitiesService { }; } - createSeriesV2DefaultStatement(): FilterStatement { + createSeriesV2DefaultStatement(): FilterStatement { return { comparison: FilterComparison.Equal, value: '', field: FilterField.SeriesName } } + + createPersonV2Filter(): FilterV2 { + return { + combination: FilterCombination.And, + statements: [], + limitTo: 0, + sortOptions: { + isAscending: true, + sortField: SortField.SortName + }, + }; + } + + createPersonV2DefaultStatement(): FilterStatement { + return { + comparison: FilterComparison.Equal, + value: '', + field: PersonFilterField.Name + } + } } diff --git a/UI/Web/src/app/want-to-read/_components/want-to-read/want-to-read.component.ts b/UI/Web/src/app/want-to-read/_components/want-to-read/want-to-read.component.ts index 91fc9f143..48c518e22 100644 --- a/UI/Web/src/app/want-to-read/_components/want-to-read/want-to-read.component.ts +++ b/UI/Web/src/app/want-to-read/_components/want-to-read/want-to-read.component.ts @@ -1,43 +1,46 @@ -import { DOCUMENT, NgStyle, NgIf, DecimalPipe } from '@angular/common'; +import {DecimalPipe, DOCUMENT, NgStyle} from '@angular/common'; import { AfterContentChecked, ChangeDetectionStrategy, ChangeDetectorRef, - Component, DestroyRef, + Component, + DestroyRef, ElementRef, EventEmitter, - HostListener, inject, Inject, OnInit, ViewChild } from '@angular/core'; -import { Title } from '@angular/platform-browser'; -import { Router, ActivatedRoute } from '@angular/router'; -import { take, debounceTime } from 'rxjs'; -import { BulkSelectionService } from 'src/app/cards/bulk-selection.service'; -import { FilterSettings } from 'src/app/metadata-filter/filter-settings'; -import { FilterUtilitiesService } from 'src/app/shared/_services/filter-utilities.service'; -import { UtilityService, KEY_CODES } from 'src/app/shared/_services/utility.service'; -import { SeriesRemovedEvent } from 'src/app/_models/events/series-removed-event'; -import { JumpKey } from 'src/app/_models/jumpbar/jump-key'; -import { Pagination } from 'src/app/_models/pagination'; -import { Series } from 'src/app/_models/series'; -import { FilterEvent } from 'src/app/_models/metadata/series-filter'; -import { Action, ActionItem } from 'src/app/_services/action-factory.service'; -import { ActionService } from 'src/app/_services/action.service'; -import { ImageService } from 'src/app/_services/image.service'; -import { JumpbarService } from 'src/app/_services/jumpbar.service'; -import { MessageHubService, EVENTS } from 'src/app/_services/message-hub.service'; -import { ScrollService } from 'src/app/_services/scroll.service'; -import { SeriesService } from 'src/app/_services/series.service'; +import {Title} from '@angular/platform-browser'; +import {ActivatedRoute, Router} from '@angular/router'; +import {debounceTime, take} from 'rxjs'; +import {BulkSelectionService} from 'src/app/cards/bulk-selection.service'; +import {FilterSettings} from 'src/app/metadata-filter/filter-settings'; +import {FilterUtilitiesService} from 'src/app/shared/_services/filter-utilities.service'; +import {UtilityService} from 'src/app/shared/_services/utility.service'; +import {SeriesRemovedEvent} from 'src/app/_models/events/series-removed-event'; +import {JumpKey} from 'src/app/_models/jumpbar/jump-key'; +import {Pagination} from 'src/app/_models/pagination'; +import {Series} from 'src/app/_models/series'; +import {FilterEvent} from 'src/app/_models/metadata/series-filter'; +import {Action, ActionItem} from 'src/app/_services/action-factory.service'; +import {ActionService} from 'src/app/_services/action.service'; +import {ImageService} from 'src/app/_services/image.service'; +import {JumpbarService} from 'src/app/_services/jumpbar.service'; +import {EVENTS, MessageHubService} from 'src/app/_services/message-hub.service'; +import {ScrollService} from 'src/app/_services/scroll.service'; +import {SeriesService} from 'src/app/_services/series.service'; import {takeUntilDestroyed} from "@angular/core/rxjs-interop"; -import { SeriesCardComponent } from '../../../cards/series-card/series-card.component'; -import { CardDetailLayoutComponent } from '../../../cards/card-detail-layout/card-detail-layout.component'; -import { BulkOperationsComponent } from '../../../cards/bulk-operations/bulk-operations.component'; -import { SideNavCompanionBarComponent } from '../../../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component'; +import {SeriesCardComponent} from '../../../cards/series-card/series-card.component'; +import {CardDetailLayoutComponent} from '../../../cards/card-detail-layout/card-detail-layout.component'; +import {BulkOperationsComponent} from '../../../cards/bulk-operations/bulk-operations.component'; +import { + SideNavCompanionBarComponent +} from '../../../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component'; import {translate, TranslocoDirective} from "@jsverse/transloco"; -import {SeriesFilterV2} from "../../../_models/metadata/v2/series-filter-v2"; +import {FilterV2} from "../../../_models/metadata/v2/filter-v2"; +import {FilterField} from "../../../_models/metadata/v2/filter-field"; @Component({ @@ -56,11 +59,11 @@ export class WantToReadComponent implements OnInit, AfterContentChecked { isLoading: boolean = true; series: Array = []; pagination: Pagination = new Pagination(); - filter: SeriesFilterV2 | undefined = undefined; - filterSettings: FilterSettings = new FilterSettings(); + filter: FilterV2 | undefined = undefined; + filterSettings: FilterSettings = new FilterSettings(); refresh: EventEmitter = new EventEmitter(); - filterActiveCheck!: SeriesFilterV2; + filterActiveCheck!: FilterV2; filterActive: boolean = false; jumpbarKeys: Array = [];