Misc Bugfixes (#2216)

* Folder watching will now appropriately ignore changes that occur in blacklisted folders.

* Fixed up recently updated from dashboard not opening a pre-sorted page. There were issues with how encoding and decoding was done plus missing code.

* Fixed up all streams from Dashboard opening to correctly filtered pages.

* All search linking now works.

* Rating tooltip and stars are bigger on mobile.

* A bit of cleanup

* Added day breakdown to user stats page.

* Removed Token checks before we write events to the history table for scrobbling.

Refactored so series holds will prevent writing events for reviews, ratings, etc.

* Fixed a potential bug where series name could be taken from a chapter that isn't the first ordered (very unlikely) for epubs.

Fixed a bug where Volume 1.5 could be selected for series-level metadata over Volume 1.

* Optimized the license check code so that users without any license entered would still take advantage of the cache layer.

* Sped up an API that checks if the library allows scrobbling

* Cleaned up the mobile CSS a bit for filters.
This commit is contained in:
Joe Milazzo 2023-08-15 16:33:39 -05:00 committed by GitHub
parent ef3e76e3e5
commit c84a3294e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 324 additions and 246 deletions

View file

@ -1,5 +1,5 @@
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, Router} from '@angular/router';
import {ActivatedRouteSnapshot, Params, Router} from '@angular/router';
import {Pagination} from 'src/app/_models/pagination';
import {SortField, SortOptions} from 'src/app/_models/metadata/series-filter';
import {MetadataService} from "../../_services/metadata.service";
@ -9,50 +9,17 @@ import {FilterCombination} from "../../_models/metadata/v2/filter-combination";
import {FilterField} from "../../_models/metadata/v2/filter-field";
import {FilterComparison} from "../../_models/metadata/v2/filter-comparison";
/**
* Used to pass state between the filter and the url
*/
export enum FilterQueryParam {
Format = 'format',
Genres = 'genres',
AgeRating = 'ageRating',
PublicationStatus = 'publicationStatus',
Tags = 'tags',
Languages = 'languages',
CollectionTags = 'collectionTags',
Libraries = 'libraries',
Writers = 'writers',
Artists = 'artists',
Character = 'character',
Colorist = 'colorist',
CoverArtists = 'coverArtists',
Editor = 'editor',
Inker = 'inker',
Letterer = 'letterer',
Penciller = 'penciller',
Publisher = 'publisher',
Translator = 'translators',
ReadStatus = 'readStatus',
SortBy = 'sortBy',
Rating = 'rating',
Name = 'name',
/**
* This is a pagination control
*/
Page = 'page',
/**
* Special case for the UI. Does not trigger filtering
*/
None = 'none'
}
const sortOptionsKey = 'sortOptions=';
const statementsKey = 'stmts=';
const limitToKey = 'limitTo=';
const combinationKey = 'combination=';
@Injectable({
providedIn: 'root'
})
export class FilterUtilitiesService {
constructor(private metadataService: MetadataService, private router: Router) {
}
constructor(private metadataService: MetadataService, private router: Router) {}
applyFilter(page: Array<any>, filter: FilterField, comparison: FilterComparison, value: string) {
const dto: SeriesFilterV2 = {
@ -61,8 +28,14 @@ export class FilterUtilitiesService {
limitTo: 0
};
console.log('applying filter: ', this.urlFromFilterV2(page.join('/') + '?', dto))
this.router.navigateByUrl(this.urlFromFilterV2(page.join('/') + '?', dto));
const url = this.urlFromFilterV2(page.join('/') + '?', dto);
return this.router.navigateByUrl(url);
}
applyFilterWithParams(page: Array<any>, filter: SeriesFilterV2, extraParams: Params) {
let url = this.urlFromFilterV2(page.join('/') + '?', filter);
url += Object.keys(extraParams).map(k => `&${k}=${extraParams[k]}`).join('');
return this.router.navigateByUrl(url, extraParams);
}
/**
@ -84,7 +57,7 @@ export class FilterUtilitiesService {
/**
* Will fetch current page from route if present
* @param ActivatedRouteSnapshot to fetch page from. Must be from component else may get stale data
* @param snapshot to fetch page from. Must be from component else may get stale data
* @param itemsPerPage If you want pagination, pass non-zero number
* @returns A default pagination object
*/
@ -107,10 +80,10 @@ export class FilterUtilitiesService {
encodeSeriesFilter(filter: SeriesFilterV2) {
const encodedStatements = this.encodeFilterStatements(filter.statements);
const encodedSortOptions = filter.sortOptions ? `sortOptions=${this.encodeSortOptions(filter.sortOptions)}` : '';
const encodedLimitTo = `limitTo=${filter.limitTo}`;
const encodedSortOptions = filter.sortOptions ? `${sortOptionsKey}${this.encodeSortOptions(filter.sortOptions)}` : '';
const encodedLimitTo = `${limitToKey}${filter.limitTo}`;
return `${this.encodeName(filter.name)}stmts=${encodedStatements}&${encodedSortOptions}&${encodedLimitTo}&combination=${filter.combination}`;
return `${this.encodeName(filter.name)}${encodedStatements}&${encodedSortOptions}&${encodedLimitTo}&${combinationKey}${filter.combination}`;
}
encodeName(name: string | undefined) {
@ -124,7 +97,8 @@ export class FilterUtilitiesService {
}
encodeFilterStatements(statements: Array<FilterStatement>) {
return encodeURIComponent(statements.map(statement => {
if (statements.length === 0) return '';
return statementsKey + encodeURIComponent(statements.map(statement => {
const encodedComparison = `comparison=${statement.comparison}`;
const encodedField = `field=${statement.field}`;
const encodedValue = `value=${encodeURIComponent(statement.value)}`;
@ -144,19 +118,23 @@ export class FilterUtilitiesService {
}
const fullUrl = window.location.href.split('?')[1];
const stmtsStartIndex = fullUrl.indexOf('stmts=');
let endIndex = fullUrl.indexOf('&sortOptions=');
const stmtsStartIndex = fullUrl.indexOf(statementsKey);
let endIndex = fullUrl.indexOf('&' + sortOptionsKey);
if (endIndex < 0) {
endIndex = fullUrl.indexOf('&limitTo=');
endIndex = fullUrl.indexOf('&' + limitToKey);
}
if (stmtsStartIndex !== -1 && endIndex !== -1) {
const stmtsEncoded = fullUrl.substring(stmtsStartIndex + 6, endIndex);
if (stmtsStartIndex !== -1 || endIndex !== -1) {
// +1 is for the =
const stmtsEncoded = fullUrl.substring(stmtsStartIndex + statementsKey.length, endIndex);
filter.statements = this.decodeFilterStatements(stmtsEncoded);
}
if (queryParams.sortOptions) {
const sortOptions = this.decodeSortOptions(queryParams.sortOptions);
const optionsStartIndex = fullUrl.indexOf('&' + sortOptionsKey);
const endIndex = fullUrl.indexOf('&' + limitToKey);
const sortOptionsEncoded = fullUrl.substring(optionsStartIndex + sortOptionsKey.length + 1, endIndex);
const sortOptions = this.decodeSortOptions(sortOptionsEncoded);
if (sortOptions) {
filter.sortOptions = sortOptions;
}
@ -174,7 +152,7 @@ export class FilterUtilitiesService {
}
decodeSortOptions(encodedSortOptions: string): SortOptions | null {
const parts = encodedSortOptions.split('&');
const parts = decodeURIComponent(encodedSortOptions).split('&');
const sortFieldPart = parts.find(part => part.startsWith('sortField='));
const isAscendingPart = parts.find(part => part.startsWith('isAscending='));
@ -188,7 +166,7 @@ export class FilterUtilitiesService {
}
decodeFilterStatements(encodedStatements: string): FilterStatement[] {
const statementStrings = decodeURIComponent(encodedStatements).split(','); // I don't think this will wrk
const statementStrings = decodeURIComponent(encodedStatements).split(',');
return statementStrings.map(statementString => {
const parts = statementString.split('&');
if (parts === null || parts.length < 3) return null;