Metadata Tags (#947)
* Implemented the ability to click a metadata tag (in series detail) and load a pre-filtered view. Apply still needs to be implemented (preset load is out of sync with external filter) * Refactored people to properly use typeahead so duplicates don't happen and use an observable chain so we can update the screen correctly * Many refactoring to ensure that the timings for filtering always works
This commit is contained in:
parent
06be7de6b2
commit
80e9738f67
13 changed files with 374 additions and 293 deletions
|
|
@ -61,10 +61,10 @@
|
|||
<label for="libraries">Libraries</label>
|
||||
<app-typeahead (selectedData)="updateLibraryFilters($event)" [settings]="librarySettings" [reset]="resetTypeaheads">
|
||||
<ng-template #badgeItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
<ng-template #optionItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
</app-typeahead>
|
||||
</div>
|
||||
|
|
@ -117,13 +117,13 @@
|
|||
<!-- The People row -->
|
||||
<div class="col-md-2 mr-3" *ngIf="peopleSettings.hasOwnProperty(PersonRole.CoverArtist)">
|
||||
<div class="form-group">
|
||||
<label for="cover-artist">(Cover) Artists</label>
|
||||
<label for="cover-artist">Cover Artists</label>
|
||||
<app-typeahead (selectedData)="updatePersonFilters($event, PersonRole.CoverArtist)" [settings]="getPersonsSettings(PersonRole.CoverArtist)" [reset]="resetTypeaheads">
|
||||
<ng-template #badgeItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
<ng-template #optionItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
</app-typeahead>
|
||||
</div>
|
||||
|
|
@ -134,10 +134,10 @@
|
|||
<label for="writers">Writers</label>
|
||||
<app-typeahead (selectedData)="updatePersonFilters($event, PersonRole.Writer)" [settings]="getPersonsSettings(PersonRole.Writer)" [reset]="resetTypeaheads">
|
||||
<ng-template #badgeItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
<ng-template #optionItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
</app-typeahead>
|
||||
</div>
|
||||
|
|
@ -148,10 +148,10 @@
|
|||
<label for="publisher">Publisher</label>
|
||||
<app-typeahead (selectedData)="updatePersonFilters($event, PersonRole.Publisher)" [settings]="getPersonsSettings(PersonRole.Publisher)" [reset]="resetTypeaheads">
|
||||
<ng-template #badgeItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
<ng-template #optionItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
</app-typeahead>
|
||||
</div>
|
||||
|
|
@ -162,10 +162,10 @@
|
|||
<label for="penciller">Penciller</label>
|
||||
<app-typeahead (selectedData)="updatePersonFilters($event, PersonRole.Penciller)" [settings]="getPersonsSettings(PersonRole.Penciller)" [reset]="resetTypeaheads">
|
||||
<ng-template #badgeItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
<ng-template #optionItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
</app-typeahead>
|
||||
</div>
|
||||
|
|
@ -176,10 +176,10 @@
|
|||
<label for="letterer">Letterer</label>
|
||||
<app-typeahead (selectedData)="updatePersonFilters($event, PersonRole.Letterer)" [settings]="getPersonsSettings(PersonRole.Letterer)" [reset]="resetTypeaheads">
|
||||
<ng-template #badgeItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
<ng-template #optionItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
</app-typeahead>
|
||||
</div>
|
||||
|
|
@ -190,10 +190,10 @@
|
|||
<label for="inker">Inker</label>
|
||||
<app-typeahead (selectedData)="updatePersonFilters($event, PersonRole.Inker)" [settings]="getPersonsSettings(PersonRole.Inker)" [reset]="resetTypeaheads">
|
||||
<ng-template #badgeItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
<ng-template #optionItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
</app-typeahead>
|
||||
</div>
|
||||
|
|
@ -204,10 +204,10 @@
|
|||
<label for="editor">Editor</label>
|
||||
<app-typeahead (selectedData)="updatePersonFilters($event, PersonRole.Editor)" [settings]="getPersonsSettings(PersonRole.Editor)" [reset]="resetTypeaheads">
|
||||
<ng-template #badgeItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
<ng-template #optionItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
</app-typeahead>
|
||||
</div>
|
||||
|
|
@ -218,10 +218,10 @@
|
|||
<label for="colorist">Colorist</label>
|
||||
<app-typeahead (selectedData)="updatePersonFilters($event, PersonRole.Colorist)" [settings]="getPersonsSettings(PersonRole.Colorist)" [reset]="resetTypeaheads">
|
||||
<ng-template #badgeItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
<ng-template #optionItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
</app-typeahead>
|
||||
</div>
|
||||
|
|
@ -232,10 +232,10 @@
|
|||
<label for="character">Character</label>
|
||||
<app-typeahead (selectedData)="updatePersonFilters($event, PersonRole.Character)" [settings]="getPersonsSettings(PersonRole.Character)" [reset]="resetTypeaheads">
|
||||
<ng-template #badgeItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
<ng-template #optionItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
</app-typeahead>
|
||||
</div>
|
||||
|
|
@ -246,10 +246,10 @@
|
|||
<label for="translators">Translators</label>
|
||||
<app-typeahead (selectedData)="updatePersonFilters($event, PersonRole.Translator)" [settings]="getPersonsSettings(PersonRole.Translator)" [reset]="resetTypeaheads">
|
||||
<ng-template #badgeItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
<ng-template #optionItem let-item let-position="idx">
|
||||
{{item.title}}
|
||||
{{item.name}}
|
||||
</ng-template>
|
||||
</app-typeahead>
|
||||
</div>
|
||||
|
|
@ -328,9 +328,9 @@
|
|||
<div class="form-group">
|
||||
<label for="sort-options">Sort By</label>
|
||||
<button class="btn btn-sm btn-secondary-outline" (click)="updateSortOrder()" style="height: 25px; padding-bottom: 0px;">
|
||||
<i class="fa fa-arrow-down" title="Ascending" *ngIf="isAscendingSort; else descSort"></i>
|
||||
<i class="fa fa-arrow-up" title="Ascending" *ngIf="isAscendingSort; else descSort"></i>
|
||||
<ng-template #descSort>
|
||||
<i class="fa fa-arrow-up" title="Descending"></i>
|
||||
<i class="fa fa-arrow-down" title="Descending"></i>
|
||||
</ng-template>
|
||||
</button>
|
||||
<select id="sort-options" class="form-control" formControlName="sortField" style="height: 38px;">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Component, ContentChild, EventEmitter, Input, OnDestroy, OnInit, Output, TemplateRef } from '@angular/core';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
import { Observable, of, ReplaySubject, Subject } from 'rxjs';
|
||||
import { forkJoin, Observable, of, ReplaySubject, Subject } from 'rxjs';
|
||||
import { map, takeUntil } from 'rxjs/operators';
|
||||
import { UtilityService } from 'src/app/shared/_services/utility.service';
|
||||
import { TypeaheadSettings } from 'src/app/typeahead/typeahead-settings';
|
||||
|
|
@ -34,13 +34,16 @@ export class FilterSettings {
|
|||
peopleDisabled = false;
|
||||
readProgressDisabled = false;
|
||||
ratingDisabled = false;
|
||||
presetLibraryId = 0;
|
||||
presetCollectionId = 0;
|
||||
sortDisabled = false;
|
||||
ageRatingDisabled = false;
|
||||
tagsDisabled = false;
|
||||
languageDisabled = false;
|
||||
publicationStatusDisabled = false;
|
||||
presets: SeriesFilter | undefined;
|
||||
/**
|
||||
* Should the filter section be open by default
|
||||
*/
|
||||
openByDefault = false;
|
||||
}
|
||||
|
||||
@Component({
|
||||
|
|
@ -65,17 +68,16 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
@Output() applyFilter: EventEmitter<SeriesFilter> = new EventEmitter();
|
||||
|
||||
@ContentChild('cardItem') itemTemplate!: TemplateRef<any>;
|
||||
|
||||
|
||||
formatSettings: TypeaheadSettings<FilterItem<MangaFormat>> = new TypeaheadSettings();
|
||||
librarySettings: TypeaheadSettings<FilterItem<Library>> = new TypeaheadSettings();
|
||||
genreSettings: TypeaheadSettings<FilterItem<Genre>> = new TypeaheadSettings();
|
||||
collectionSettings: TypeaheadSettings<FilterItem<CollectionTag>> = new TypeaheadSettings();
|
||||
ageRatingSettings: TypeaheadSettings<FilterItem<AgeRatingDto>> = new TypeaheadSettings();
|
||||
publicationStatusSettings: TypeaheadSettings<FilterItem<PublicationStatusDto>> = new TypeaheadSettings();
|
||||
tagsSettings: TypeaheadSettings<FilterItem<Tag>> = new TypeaheadSettings();
|
||||
languageSettings: TypeaheadSettings<FilterItem<Language>> = new TypeaheadSettings();
|
||||
peopleSettings: {[PersonRole: string]: TypeaheadSettings<FilterItem<Person>>} = {};
|
||||
librarySettings: TypeaheadSettings<Library> = new TypeaheadSettings();
|
||||
genreSettings: TypeaheadSettings<Genre> = new TypeaheadSettings();
|
||||
collectionSettings: TypeaheadSettings<CollectionTag> = new TypeaheadSettings();
|
||||
ageRatingSettings: TypeaheadSettings<AgeRatingDto> = new TypeaheadSettings();
|
||||
publicationStatusSettings: TypeaheadSettings<PublicationStatusDto> = new TypeaheadSettings();
|
||||
tagsSettings: TypeaheadSettings<Tag> = new TypeaheadSettings();
|
||||
languageSettings: TypeaheadSettings<Language> = new TypeaheadSettings();
|
||||
peopleSettings: {[PersonRole: string]: TypeaheadSettings<Person>} = {};
|
||||
resetTypeaheads: Subject<boolean> = new ReplaySubject(1);
|
||||
|
||||
/**
|
||||
|
|
@ -85,8 +87,6 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
|
||||
filter!: SeriesFilter;
|
||||
libraries: Array<FilterItem<Library>> = [];
|
||||
genres: Array<FilterItem<Genre>> = [];
|
||||
persons: Array<FilterItem<Person>> = [];
|
||||
|
||||
|
||||
readProgressGroup!: FormGroup;
|
||||
|
|
@ -152,24 +152,12 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
|
||||
ngOnInit(): void {
|
||||
this.trackByIdentity = (index: number, item: any) => `${this.header}_${this.pagination?.currentPage}_${this.updateApplied}`;
|
||||
this.setupFormatTypeahead();
|
||||
|
||||
if (this.filterSettings === undefined) {
|
||||
this.filterSettings = new FilterSettings();
|
||||
}
|
||||
|
||||
this.libraryService.getLibrariesForMember().subscribe(libs => {
|
||||
this.libraries = libs.map(lib => {
|
||||
return {
|
||||
title: lib.name,
|
||||
value: lib,
|
||||
selected: true,
|
||||
}
|
||||
});
|
||||
this.setupTypeaheads();
|
||||
});
|
||||
|
||||
|
||||
this.setupTypeaheads();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
|
|
@ -178,14 +166,25 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
setupTypeaheads() {
|
||||
this.setupLibraryTypeahead();
|
||||
this.setupCollectionTagTypeahead();
|
||||
this.setupPersonTypeahead();
|
||||
this.setupAgeRatingSettings();
|
||||
this.setupPublicationStatusSettings();
|
||||
this.setupTagSettings();
|
||||
this.setupLanguageSettings();
|
||||
this.setupGenreTypeahead();
|
||||
|
||||
this.setupFormatTypeahead();
|
||||
|
||||
forkJoin([
|
||||
this.setupLibraryTypeahead(),
|
||||
this.setupCollectionTagTypeahead(),
|
||||
this.setupAgeRatingSettings(),
|
||||
this.setupPublicationStatusSettings(),
|
||||
this.setupTagSettings(),
|
||||
this.setupLanguageSettings(),
|
||||
this.setupGenreTypeahead(),
|
||||
this.setupPersonTypeahead(),
|
||||
]).subscribe(results => {
|
||||
this.resetTypeaheads.next(true);
|
||||
if (this.filterSettings.openByDefault) {
|
||||
this.filteringCollapsed = false;
|
||||
}
|
||||
this.apply();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -200,6 +199,12 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
const f = filter.toLowerCase();
|
||||
return options.filter(m => m.title.toLowerCase() === f);
|
||||
}
|
||||
|
||||
if (this.filterSettings.presets?.formats && this.filterSettings.presets?.formats.length > 0) {
|
||||
this.formatSettings.savedData = mangaFormatFilters.filter(item => this.filterSettings.presets?.formats.includes(item.value));
|
||||
this.filter.formats = this.formatSettings.savedData.map(item => item.value);
|
||||
this.resetTypeaheads.next(true);
|
||||
}
|
||||
}
|
||||
|
||||
setupLibraryTypeahead() {
|
||||
|
|
@ -209,18 +214,21 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
this.librarySettings.unique = true;
|
||||
this.librarySettings.addIfNonExisting = false;
|
||||
this.librarySettings.fetchFn = (filter: string) => {
|
||||
return of (this.libraries)
|
||||
return this.libraryService.getLibrariesForMember();
|
||||
};
|
||||
this.librarySettings.compareFn = (options: FilterItem<Library>[], filter: string) => {
|
||||
this.librarySettings.compareFn = (options: Library[], filter: string) => {
|
||||
const f = filter.toLowerCase();
|
||||
return options.filter(m => m.title.toLowerCase() === f);
|
||||
return options.filter(m => m.name.toLowerCase() === f);
|
||||
}
|
||||
|
||||
if (this.filterSettings.presetLibraryId > 0) {
|
||||
this.librarySettings.savedData = this.libraries.filter(item => item.value.id === this.filterSettings.presetLibraryId);
|
||||
this.filter.libraries = this.librarySettings.savedData.map(item => item.value.id);
|
||||
this.resetTypeaheads.next(true); // For some reason library just doesn't update properly with savedData
|
||||
if (this.filterSettings.presets?.libraries && this.filterSettings.presets?.libraries.length > 0) {
|
||||
return this.librarySettings.fetchFn('').pipe(map(libraries => {
|
||||
this.librarySettings.savedData = libraries.filter(item => this.filterSettings.presets?.libraries.includes(item.id));
|
||||
this.filter.libraries = this.librarySettings.savedData.map(item => item.id);
|
||||
return of(true);
|
||||
}));
|
||||
}
|
||||
return of(true);
|
||||
}
|
||||
|
||||
setupGenreTypeahead() {
|
||||
|
|
@ -230,20 +238,21 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
this.genreSettings.unique = true;
|
||||
this.genreSettings.addIfNonExisting = false;
|
||||
this.genreSettings.fetchFn = (filter: string) => {
|
||||
return this.metadataService.getAllGenres(this.filter.libraries).pipe(map(genres => {
|
||||
return genres.map(genre => {
|
||||
return {
|
||||
title: genre.title,
|
||||
value: genre,
|
||||
selected: false,
|
||||
}
|
||||
})
|
||||
}));
|
||||
return this.metadataService.getAllGenres(this.filter.libraries);
|
||||
};
|
||||
this.genreSettings.compareFn = (options: FilterItem<Genre>[], filter: string) => {
|
||||
this.genreSettings.compareFn = (options: Genre[], filter: string) => {
|
||||
const f = filter.toLowerCase();
|
||||
return options.filter(m => m.title.toLowerCase() === f);
|
||||
}
|
||||
|
||||
if (this.filterSettings.presets?.genres && this.filterSettings.presets?.genres.length > 0) {
|
||||
return this.genreSettings.fetchFn('').pipe(map(genres => {
|
||||
this.genreSettings.savedData = genres.filter(item => this.filterSettings.presets?.genres.includes(item.id));
|
||||
this.filter.genres = this.genreSettings.savedData.map(item => item.id);
|
||||
return of(true);
|
||||
}));
|
||||
}
|
||||
return of(true);
|
||||
}
|
||||
|
||||
setupAgeRatingSettings() {
|
||||
|
|
@ -253,20 +262,21 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
this.ageRatingSettings.unique = true;
|
||||
this.ageRatingSettings.addIfNonExisting = false;
|
||||
this.ageRatingSettings.fetchFn = (filter: string) => {
|
||||
return this.metadataService.getAllAgeRatings(this.filter.libraries).pipe(map(ratings => {
|
||||
return ratings.map(rating => {
|
||||
return {
|
||||
title: rating.title,
|
||||
value: rating,
|
||||
selected: false,
|
||||
}
|
||||
})
|
||||
}));
|
||||
return this.metadataService.getAllAgeRatings(this.filter.libraries);
|
||||
};
|
||||
this.ageRatingSettings.compareFn = (options: FilterItem<AgeRatingDto>[], filter: string) => {
|
||||
this.ageRatingSettings.compareFn = (options: AgeRatingDto[], filter: string) => {
|
||||
const f = filter.toLowerCase();
|
||||
return options.filter(m => m.title.toLowerCase() === f && this.utilityService.filter(m.title, filter));
|
||||
}
|
||||
|
||||
if (this.filterSettings.presets?.ageRating && this.filterSettings.presets?.ageRating.length > 0) {
|
||||
return this.ageRatingSettings.fetchFn('').pipe(map(rating => {
|
||||
this.ageRatingSettings.savedData = rating.filter(item => this.filterSettings.presets?.ageRating.includes(item.value));
|
||||
this.filter.ageRating = this.ageRatingSettings.savedData.map(item => item.value);
|
||||
return of(true);
|
||||
}));
|
||||
}
|
||||
return of(true);
|
||||
}
|
||||
|
||||
setupPublicationStatusSettings() {
|
||||
|
|
@ -276,20 +286,21 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
this.publicationStatusSettings.unique = true;
|
||||
this.publicationStatusSettings.addIfNonExisting = false;
|
||||
this.publicationStatusSettings.fetchFn = (filter: string) => {
|
||||
return this.metadataService.getAllPublicationStatus(this.filter.libraries).pipe(map(statuses => {
|
||||
return statuses.map(status => {
|
||||
return {
|
||||
title: status.title,
|
||||
value: status,
|
||||
selected: false,
|
||||
}
|
||||
})
|
||||
}));
|
||||
return this.metadataService.getAllPublicationStatus(this.filter.libraries);
|
||||
};
|
||||
this.publicationStatusSettings.compareFn = (options: FilterItem<PublicationStatusDto>[], filter: string) => {
|
||||
this.publicationStatusSettings.compareFn = (options: PublicationStatusDto[], filter: string) => {
|
||||
const f = filter.toLowerCase();
|
||||
return options.filter(m => m.title.toLowerCase() === f && this.utilityService.filter(m.title, filter));
|
||||
}
|
||||
|
||||
if (this.filterSettings.presets?.publicationStatus && this.filterSettings.presets?.publicationStatus.length > 0) {
|
||||
return this.publicationStatusSettings.fetchFn('').pipe(map(statuses => {
|
||||
this.publicationStatusSettings.savedData = statuses.filter(item => this.filterSettings.presets?.publicationStatus.includes(item.value));
|
||||
this.filter.publicationStatus = this.publicationStatusSettings.savedData.map(item => item.value);
|
||||
return of(true);
|
||||
}));
|
||||
}
|
||||
return of(true);
|
||||
}
|
||||
|
||||
setupTagSettings() {
|
||||
|
|
@ -299,20 +310,21 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
this.tagsSettings.unique = true;
|
||||
this.tagsSettings.addIfNonExisting = false;
|
||||
this.tagsSettings.fetchFn = (filter: string) => {
|
||||
return this.metadataService.getAllTags(this.filter.libraries).pipe(map(tags => {
|
||||
return tags.map(tag => {
|
||||
return {
|
||||
title: tag.title,
|
||||
value: tag,
|
||||
selected: false,
|
||||
}
|
||||
})
|
||||
}));
|
||||
return this.metadataService.getAllTags(this.filter.libraries);
|
||||
};
|
||||
this.tagsSettings.compareFn = (options: FilterItem<Tag>[], filter: string) => {
|
||||
this.tagsSettings.compareFn = (options: Tag[], filter: string) => {
|
||||
const f = filter.toLowerCase();
|
||||
return options.filter(m => m.title.toLowerCase() === f && this.utilityService.filter(m.title, filter));
|
||||
}
|
||||
|
||||
if (this.filterSettings.presets?.tags && this.filterSettings.presets?.tags.length > 0) {
|
||||
return this.tagsSettings.fetchFn('').pipe(map(tags => {
|
||||
this.tagsSettings.savedData = tags.filter(item => this.filterSettings.presets?.tags.includes(item.id));
|
||||
this.filter.tags = this.tagsSettings.savedData.map(item => item.id);
|
||||
return of(true);
|
||||
}));
|
||||
}
|
||||
return of(true);
|
||||
}
|
||||
|
||||
setupLanguageSettings() {
|
||||
|
|
@ -322,20 +334,21 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
this.languageSettings.unique = true;
|
||||
this.languageSettings.addIfNonExisting = false;
|
||||
this.languageSettings.fetchFn = (filter: string) => {
|
||||
return this.metadataService.getAllLanguages(this.filter.libraries).pipe(map(tags => {
|
||||
return tags.map(tag => {
|
||||
return {
|
||||
title: tag.title,
|
||||
value: tag,
|
||||
selected: false,
|
||||
}
|
||||
})
|
||||
}));
|
||||
return this.metadataService.getAllLanguages(this.filter.libraries);
|
||||
};
|
||||
this.languageSettings.compareFn = (options: FilterItem<Language>[], filter: string) => {
|
||||
this.languageSettings.compareFn = (options: Language[], filter: string) => {
|
||||
const f = filter.toLowerCase();
|
||||
return options.filter(m => m.title.toLowerCase() === f && this.utilityService.filter(m.title, filter));
|
||||
}
|
||||
|
||||
if (this.filterSettings.presets?.languages && this.filterSettings.presets?.languages.length > 0) {
|
||||
return this.languageSettings.fetchFn('').pipe(map(languages => {
|
||||
this.languageSettings.savedData = languages.filter(item => this.filterSettings.presets?.languages.includes(item.isoCode));
|
||||
this.filter.languages = this.languageSettings.savedData.map(item => item.isoCode);
|
||||
return of(true);
|
||||
}));
|
||||
}
|
||||
return of(true);
|
||||
}
|
||||
|
||||
setupCollectionTagTypeahead() {
|
||||
|
|
@ -345,128 +358,81 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
this.collectionSettings.unique = true;
|
||||
this.collectionSettings.addIfNonExisting = false;
|
||||
this.collectionSettings.fetchFn = (filter: string) => {
|
||||
return this.collectionTagService.allTags().pipe(map(tags => {
|
||||
return tags.map(lib => {
|
||||
return {
|
||||
title: lib.title,
|
||||
value: lib,
|
||||
selected: false,
|
||||
}
|
||||
});
|
||||
}));
|
||||
return this.collectionTagService.allTags();
|
||||
};
|
||||
this.collectionSettings.compareFn = (options: FilterItem<CollectionTag>[], filter: string) => {
|
||||
this.collectionSettings.compareFn = (options: CollectionTag[], filter: string) => {
|
||||
const f = filter.toLowerCase();
|
||||
return options.filter(m => m.title.toLowerCase() === f);
|
||||
}
|
||||
|
||||
if (this.filterSettings.presetCollectionId > 0) {
|
||||
this.collectionSettings.fetchFn('').subscribe(tags => {
|
||||
this.collectionSettings.savedData = tags.filter(item => item.value.id === this.filterSettings.presetCollectionId);
|
||||
this.filter.collectionTags = this.collectionSettings.savedData.map(item => item.value.id);
|
||||
this.resetTypeaheads.next(true);
|
||||
});
|
||||
if (this.filterSettings.presets?.collectionTags && this.filterSettings.presets?.collectionTags.length > 0) {
|
||||
return this.collectionSettings.fetchFn('').pipe(map(tags => {
|
||||
this.collectionSettings.savedData = tags.filter(item => this.filterSettings.presets?.collectionTags.includes(item.id));
|
||||
this.filter.collectionTags = this.collectionSettings.savedData.map(item => item.id);
|
||||
return of(true);
|
||||
}));
|
||||
}
|
||||
return of(true);
|
||||
}
|
||||
|
||||
applyPresets() {
|
||||
|
||||
// if (this.filterSettings.presetCollectionId > 0) {
|
||||
// this.collectionSettings.fetchFn('').subscribe(tags => {
|
||||
// this.collectionSettings.savedData = tags.filter(item => item.value.id === this.filterSettings.presetCollectionId);
|
||||
// this.filter.collectionTags = this.collectionSettings.savedData.map(item => item.value.id);
|
||||
// this.resetTypeaheads.next(true);
|
||||
// });
|
||||
// }
|
||||
updateFromPreset(id: string, peopleFilterField: Array<any>, presetField: Array<any> | undefined, role: PersonRole) {
|
||||
const personSettings = this.createBlankPersonSettings(id, role)
|
||||
if (presetField && presetField.length > 0) {
|
||||
const fetch = personSettings.fetchFn as ((filter: string) => Observable<Person[]>);
|
||||
return fetch('').pipe(map(people => {
|
||||
personSettings.savedData = people.filter(item => presetField.includes(item.id));
|
||||
peopleFilterField = personSettings.savedData.map(item => item.id);
|
||||
this.resetTypeaheads.next(true);
|
||||
this.peopleSettings[role] = personSettings;
|
||||
this.updatePersonFilters(personSettings.savedData as Person[], role);
|
||||
return true;
|
||||
}));
|
||||
} else {
|
||||
this.peopleSettings[role] = personSettings;
|
||||
return of(true);
|
||||
}
|
||||
}
|
||||
|
||||
setupPersonTypeahead() {
|
||||
this.peopleSettings = {};
|
||||
|
||||
var personSettings = this.createBlankPersonSettings('writers');
|
||||
personSettings.fetchFn = (filter: string) => {
|
||||
return this.fetchPeople(PersonRole.Writer, filter);
|
||||
};
|
||||
this.peopleSettings[PersonRole.Writer] = personSettings;
|
||||
|
||||
personSettings = this.createBlankPersonSettings('character');
|
||||
personSettings.fetchFn = (filter: string) => {
|
||||
return this.fetchPeople(PersonRole.Character, filter);
|
||||
};
|
||||
this.peopleSettings[PersonRole.Character] = personSettings;
|
||||
|
||||
personSettings = this.createBlankPersonSettings('colorist');
|
||||
personSettings.fetchFn = (filter: string) => {
|
||||
return this.fetchPeople(PersonRole.Colorist, filter);
|
||||
};
|
||||
this.peopleSettings[PersonRole.Colorist] = personSettings;
|
||||
|
||||
personSettings = this.createBlankPersonSettings('cover-artist');
|
||||
personSettings.fetchFn = (filter: string) => {
|
||||
return this.fetchPeople(PersonRole.CoverArtist, filter);
|
||||
};
|
||||
this.peopleSettings[PersonRole.CoverArtist] = personSettings;
|
||||
|
||||
personSettings = this.createBlankPersonSettings('editor');
|
||||
personSettings.fetchFn = (filter: string) => {
|
||||
return this.fetchPeople(PersonRole.Editor, filter);
|
||||
};
|
||||
this.peopleSettings[PersonRole.Editor] = personSettings;
|
||||
|
||||
personSettings = this.createBlankPersonSettings('inker');
|
||||
personSettings.fetchFn = (filter: string) => {
|
||||
return this.fetchPeople(PersonRole.Inker, filter);
|
||||
};
|
||||
this.peopleSettings[PersonRole.Inker] = personSettings;
|
||||
|
||||
personSettings = this.createBlankPersonSettings('letterer');
|
||||
personSettings.fetchFn = (filter: string) => {
|
||||
return this.fetchPeople(PersonRole.Letterer, filter);
|
||||
};
|
||||
this.peopleSettings[PersonRole.Letterer] = personSettings;
|
||||
|
||||
personSettings = this.createBlankPersonSettings('penciller');
|
||||
personSettings.fetchFn = (filter: string) => {
|
||||
return this.fetchPeople(PersonRole.Penciller, filter);
|
||||
};
|
||||
this.peopleSettings[PersonRole.Penciller] = personSettings;
|
||||
|
||||
personSettings = this.createBlankPersonSettings('publisher');
|
||||
personSettings.fetchFn = (filter: string) => {
|
||||
return this.fetchPeople(PersonRole.Publisher, filter);
|
||||
};
|
||||
this.peopleSettings[PersonRole.Publisher] = personSettings;
|
||||
|
||||
personSettings = this.createBlankPersonSettings('translators');
|
||||
personSettings.fetchFn = (filter: string) => {
|
||||
return this.fetchPeople(PersonRole.Translator, filter);
|
||||
};
|
||||
this.peopleSettings[PersonRole.Translator] = personSettings;
|
||||
}
|
||||
|
||||
fetchPeople(role: PersonRole, filter: string): Observable<FilterItem<Person>[]> {
|
||||
return this.metadataService.getAllPeople(this.filter.libraries).pipe(map(people => {
|
||||
return people.filter(p => p.role == role && this.utilityService.filter(p.name, filter)).map((p: Person) => {
|
||||
return {
|
||||
title: p.name,
|
||||
value: p,
|
||||
selected: false,
|
||||
}
|
||||
});
|
||||
return forkJoin([
|
||||
this.updateFromPreset('writers', this.filter.writers, this.filterSettings.presets?.writers, PersonRole.Writer),
|
||||
this.updateFromPreset('character', this.filter.character, this.filterSettings.presets?.character, PersonRole.Character),
|
||||
this.updateFromPreset('colorist', this.filter.colorist, this.filterSettings.presets?.colorist, PersonRole.Colorist),
|
||||
this.updateFromPreset('cover-artist', this.filter.coverArtist, this.filterSettings.presets?.coverArtist, PersonRole.CoverArtist),
|
||||
this.updateFromPreset('editor', this.filter.editor, this.filterSettings.presets?.editor, PersonRole.Editor),
|
||||
this.updateFromPreset('inker', this.filter.inker, this.filterSettings.presets?.inker, PersonRole.Inker),
|
||||
this.updateFromPreset('letterer', this.filter.letterer, this.filterSettings.presets?.letterer, PersonRole.Letterer),
|
||||
this.updateFromPreset('penciller', this.filter.penciller, this.filterSettings.presets?.penciller, PersonRole.Penciller),
|
||||
this.updateFromPreset('publisher', this.filter.publisher, this.filterSettings.presets?.publisher, PersonRole.Publisher),
|
||||
this.updateFromPreset('translators', this.filter.translators, this.filterSettings.presets?.translators, PersonRole.Translator)
|
||||
]).pipe(map(results => {
|
||||
this.resetTypeaheads.next(true);
|
||||
return of(true);
|
||||
}));
|
||||
}
|
||||
|
||||
createBlankPersonSettings(id: string) {
|
||||
var personSettings = new TypeaheadSettings<FilterItem<Person>>();
|
||||
fetchPeople(role: PersonRole, filter: string) {
|
||||
return this.metadataService.getAllPeople(this.filter.libraries).pipe(map(people => {
|
||||
return people.filter(p => p.role == role && this.utilityService.filter(p.name, filter));
|
||||
}));
|
||||
}
|
||||
|
||||
createBlankPersonSettings(id: string, role: PersonRole) {
|
||||
var personSettings = new TypeaheadSettings<Person>();
|
||||
personSettings.minCharacters = 0;
|
||||
personSettings.multiple = true;
|
||||
personSettings.unique = true;
|
||||
personSettings.addIfNonExisting = false;
|
||||
personSettings.id = id;
|
||||
personSettings.compareFn = (options: FilterItem<Person>[], filter: string) => {
|
||||
personSettings.compareFn = (options: Person[], filter: string) => {
|
||||
const f = filter.toLowerCase();
|
||||
return options.filter(m => m.title.toLowerCase() === f);
|
||||
return options.filter(m => m.name.toLowerCase() === f);
|
||||
}
|
||||
personSettings.fetchFn = (filter: string) => {
|
||||
return this.fetchPeople(role, filter);
|
||||
};
|
||||
return personSettings;
|
||||
}
|
||||
|
||||
|
|
@ -491,75 +457,75 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
|
||||
updateFormatFilters(formats: FilterItem<MangaFormat>[]) {
|
||||
this.filter.formats = formats.map(item => item.value) || [];
|
||||
updateFormatFilters(formats: MangaFormat[]) {
|
||||
this.filter.formats = formats.map(item => item) || [];
|
||||
}
|
||||
|
||||
updateLibraryFilters(libraries: FilterItem<Library>[]) {
|
||||
this.filter.libraries = libraries.map(item => item.value.id) || [];
|
||||
updateLibraryFilters(libraries: Library[]) {
|
||||
this.filter.libraries = libraries.map(item => item.id) || [];
|
||||
}
|
||||
|
||||
updateGenreFilters(genres: FilterItem<Genre>[]) {
|
||||
this.filter.genres = genres.map(item => item.value.id) || [];
|
||||
updateGenreFilters(genres: Genre[]) {
|
||||
this.filter.genres = genres.map(item => item.id) || [];
|
||||
}
|
||||
|
||||
updateTagFilters(tags: FilterItem<Tag>[]) {
|
||||
this.filter.tags = tags.map(item => item.value.id) || [];
|
||||
updateTagFilters(tags: Tag[]) {
|
||||
this.filter.tags = tags.map(item => item.id) || [];
|
||||
}
|
||||
|
||||
updatePersonFilters(persons: FilterItem<Person>[], role: PersonRole) {
|
||||
updatePersonFilters(persons: Person[], role: PersonRole) {
|
||||
switch (role) {
|
||||
case PersonRole.CoverArtist:
|
||||
this.filter.coverArtist = persons.map(p => p.value.id);
|
||||
this.filter.coverArtist = persons.map(p => p.id);
|
||||
break;
|
||||
case PersonRole.Character:
|
||||
this.filter.character = persons.map(p => p.value.id);
|
||||
this.filter.character = persons.map(p => p.id);
|
||||
break;
|
||||
case PersonRole.Colorist:
|
||||
this.filter.colorist = persons.map(p => p.value.id);
|
||||
this.filter.colorist = persons.map(p => p.id);
|
||||
break;
|
||||
case PersonRole.Editor:
|
||||
this.filter.editor = persons.map(p => p.value.id);
|
||||
this.filter.editor = persons.map(p => p.id);
|
||||
break;
|
||||
case PersonRole.Inker:
|
||||
this.filter.inker = persons.map(p => p.value.id);
|
||||
this.filter.inker = persons.map(p => p.id);
|
||||
break;
|
||||
case PersonRole.Letterer:
|
||||
this.filter.letterer = persons.map(p => p.value.id);
|
||||
this.filter.letterer = persons.map(p => p.id);
|
||||
break;
|
||||
case PersonRole.Penciller:
|
||||
this.filter.penciller = persons.map(p => p.value.id);
|
||||
this.filter.penciller = persons.map(p => p.id);
|
||||
break;
|
||||
case PersonRole.Publisher:
|
||||
this.filter.publisher = persons.map(p => p.value.id);
|
||||
this.filter.publisher = persons.map(p => p.id);
|
||||
break;
|
||||
case PersonRole.Writer:
|
||||
this.filter.writers = persons.map(p => p.value.id);
|
||||
this.filter.writers = persons.map(p => p.id);
|
||||
break;
|
||||
case PersonRole.Translator:
|
||||
this.filter.translators = persons.map(p => p.value.id);
|
||||
this.filter.translators = persons.map(p => p.id);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
updateCollectionFilters(tags: FilterItem<CollectionTag>[]) {
|
||||
this.filter.collectionTags = tags.map(item => item.value.id) || [];
|
||||
updateCollectionFilters(tags: CollectionTag[]) {
|
||||
this.filter.collectionTags = tags.map(item => item.id) || [];
|
||||
}
|
||||
|
||||
updateRating(rating: any) {
|
||||
this.filter.rating = rating;
|
||||
}
|
||||
|
||||
updateAgeRating(ratingDtos: FilterItem<AgeRatingDto>[]) {
|
||||
this.filter.ageRating = ratingDtos.map(item => item.value.value) || [];
|
||||
updateAgeRating(ratingDtos: AgeRatingDto[]) {
|
||||
this.filter.ageRating = ratingDtos.map(item => item.value) || [];
|
||||
}
|
||||
|
||||
updatePublicationStatus(dtos: FilterItem<PublicationStatusDto>[]) {
|
||||
this.filter.publicationStatus = dtos.map(item => item.value.value) || [];
|
||||
updatePublicationStatus(dtos: PublicationStatusDto[]) {
|
||||
this.filter.publicationStatus = dtos.map(item => item.value) || [];
|
||||
}
|
||||
|
||||
updateLanguageRating(languages: FilterItem<Language>[]) {
|
||||
this.filter.languages = languages.map(item => item.value.isoCode) || [];
|
||||
updateLanguageRating(languages: Language[]) {
|
||||
this.filter.languages = languages.map(item => item.isoCode) || [];
|
||||
}
|
||||
|
||||
updateReadStatus(status: string) {
|
||||
|
|
@ -595,12 +561,8 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy {
|
|||
this.readProgressGroup.get('inProgress')?.setValue(true);
|
||||
this.sortGroup.get('sortField')?.setValue(SortField.SortName);
|
||||
this.isAscendingSort = true;
|
||||
// Apply any presets
|
||||
// Apply any presets which will trigger the apply
|
||||
this.setupTypeaheads();
|
||||
this.resetTypeaheads.next(true);
|
||||
|
||||
this.applyFilter.emit(this.filter);
|
||||
this.updateApplied++;
|
||||
}
|
||||
|
||||
apply() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue