diff --git a/ui/v2.5/src/models/list-filter/criteria/country.ts b/ui/v2.5/src/models/list-filter/criteria/country.ts index 2fa24790022..36c52a9f789 100644 --- a/ui/v2.5/src/models/list-filter/criteria/country.ts +++ b/ui/v2.5/src/models/list-filter/criteria/country.ts @@ -1,13 +1,24 @@ import { IntlShape } from "react-intl"; import { CriterionModifier } from "src/core/generated-graphql"; import { getCountryByISO } from "src/utils/country"; -import { StringCriterion, StringCriterionOption } from "./criterion"; +import { + CriterionOption, + StringCriterion, + StringCriterionOption, +} from "./criterion"; -const countryCriterionOption = new StringCriterionOption("country", "country"); +export const CountryCriterionOption = new CriterionOption({ + messageID: "country", + type: "country", + modifierOptions: StringCriterionOption.modifierOptions, + defaultModifier: StringCriterionOption.defaultModifier, + makeCriterion: () => new CountryCriterion(), + inputType: StringCriterionOption.inputType, +}); export class CountryCriterion extends StringCriterion { constructor() { - super(countryCriterionOption); + super(CountryCriterionOption); } protected getLabelValue(intl: IntlShape) { diff --git a/ui/v2.5/src/models/list-filter/criteria/criterion.ts b/ui/v2.5/src/models/list-filter/criteria/criterion.ts index feee489b981..eab7e98a24b 100644 --- a/ui/v2.5/src/models/list-filter/criteria/criterion.ts +++ b/ui/v2.5/src/models/list-filter/criteria/criterion.ts @@ -10,6 +10,7 @@ import { PHashDuplicationCriterionInput, DateCriterionInput, TimestampCriterionInput, + ConfigDataFragment, } from "src/core/generated-graphql"; import DurationUtils from "src/utils/duration"; import { @@ -193,7 +194,10 @@ interface ICriterionOptionsParams { modifierOptions?: CriterionModifier[]; defaultModifier?: CriterionModifier; options?: Option[]; - makeCriterion: () => Criterion; + makeCriterion: ( + o: CriterionOption, + config?: ConfigDataFragment + ) => Criterion; } export class CriterionOption { public readonly messageID: string; @@ -203,7 +207,8 @@ export class CriterionOption { public readonly options: Option[] | undefined; public readonly inputType: InputType; public readonly makeCriterionFn: ( - o: CriterionOption + o: CriterionOption, + config?: ConfigDataFragment ) => Criterion; constructor(options: ICriterionOptionsParams) { @@ -216,29 +221,34 @@ export class CriterionOption { this.makeCriterionFn = options.makeCriterion; } - public makeCriterion() { - return this.makeCriterionFn(this); + public makeCriterion(config?: ConfigDataFragment) { + return this.makeCriterionFn(this, config); } } export class StringCriterionOption extends CriterionOption { + public static readonly modifierOptions = [ + CriterionModifier.Equals, + CriterionModifier.NotEquals, + CriterionModifier.Includes, + CriterionModifier.Excludes, + CriterionModifier.IsNull, + CriterionModifier.NotNull, + CriterionModifier.MatchesRegex, + CriterionModifier.NotMatchesRegex, + ]; + + public static readonly defaultModifier = CriterionModifier.Equals; + public static readonly inputType = "text"; + constructor(messageID: string, type: CriterionType, options?: Option[]) { super({ messageID, type, - modifierOptions: [ - CriterionModifier.Equals, - CriterionModifier.NotEquals, - CriterionModifier.Includes, - CriterionModifier.Excludes, - CriterionModifier.IsNull, - CriterionModifier.NotNull, - CriterionModifier.MatchesRegex, - CriterionModifier.NotMatchesRegex, - ], - defaultModifier: CriterionModifier.Equals, + modifierOptions: StringCriterionOption.modifierOptions, + defaultModifier: StringCriterionOption.defaultModifier, options, - inputType: "text", + inputType: StringCriterionOption.inputType, makeCriterion: () => new StringCriterion(this), }); } diff --git a/ui/v2.5/src/models/list-filter/criteria/factory.ts b/ui/v2.5/src/models/list-filter/criteria/factory.ts index 1e20451d577..1687d97aa04 100644 --- a/ui/v2.5/src/models/list-filter/criteria/factory.ts +++ b/ui/v2.5/src/models/list-filter/criteria/factory.ts @@ -22,7 +22,8 @@ const filterModeOptions = { export function makeCriteria( mode: GQL.FilterMode, - type: CriterionType = "none" + type: CriterionType, + config?: GQL.ConfigDataFragment ) { const criterionOptions = filterModeOptions[mode]; @@ -32,5 +33,5 @@ export function makeCriteria( throw new Error(`Unknown criterion parameter name: ${type}`); } - return option?.makeCriterion(); + return option?.makeCriterion(config); } diff --git a/ui/v2.5/src/models/list-filter/criteria/rating.ts b/ui/v2.5/src/models/list-filter/criteria/rating.ts index 411981fed43..66605bcea02 100644 --- a/ui/v2.5/src/models/list-filter/criteria/rating.ts +++ b/ui/v2.5/src/models/list-filter/criteria/rating.ts @@ -1,14 +1,44 @@ import { convertFromRatingFormat, convertToRatingFormat, + defaultRatingSystemOptions, RatingSystemOptions, } from "src/utils/rating"; import { + ConfigDataFragment, CriterionModifier, IntCriterionInput, } from "../../../core/generated-graphql"; import { INumberValue } from "../types"; import { Criterion, CriterionOption } from "./criterion"; +import { IUIConfig } from "src/core/config"; + +const modifierOptions = [ + CriterionModifier.Equals, + CriterionModifier.NotEquals, + CriterionModifier.GreaterThan, + CriterionModifier.LessThan, + CriterionModifier.Between, + CriterionModifier.NotBetween, + CriterionModifier.IsNull, + CriterionModifier.NotNull, +]; + +function getRatingSystemOptions(config?: ConfigDataFragment) { + return ( + (config?.ui as IUIConfig)?.ratingSystemOptions ?? defaultRatingSystemOptions + ); +} + +export const RatingCriterionOption = new CriterionOption({ + messageID: "rating", + type: "rating100", + modifierOptions, + defaultModifier: CriterionModifier.Equals, + makeCriterion: (o, config) => + new RatingCriterion(getRatingSystemOptions(config)), + inputType: "number", +}); export class RatingCriterion extends Criterion { ratingSystem: RatingSystemOptions; @@ -50,8 +80,8 @@ export class RatingCriterion extends Criterion { } } - constructor(type: CriterionOption, ratingSystem: RatingSystemOptions) { - super(type, { value: 0, value2: undefined }); + constructor(ratingSystem: RatingSystemOptions) { + super(RatingCriterionOption, { value: 0, value2: undefined }); this.ratingSystem = ratingSystem; } } diff --git a/ui/v2.5/src/models/list-filter/filter.ts b/ui/v2.5/src/models/list-filter/filter.ts index 9e6bb863001..037540772dc 100644 --- a/ui/v2.5/src/models/list-filter/filter.ts +++ b/ui/v2.5/src/models/list-filter/filter.ts @@ -128,7 +128,11 @@ export class ListFilterModel { for (const jsonString of params.c) { try { const encodedCriterion = JSON.parse(jsonString); - const criterion = makeCriteria(this.mode, encodedCriterion.type); + const criterion = makeCriteria( + this.mode, + encodedCriterion.type, + this.config + ); // it's possible that we have unsupported criteria. Just skip if so. if (criterion) { criterion.setFromEncodedCriterion(encodedCriterion); @@ -276,7 +280,11 @@ export class ListFilterModel { this.criteria = []; if (objectFilter) { Object.keys(objectFilter).forEach((key) => { - const criterion = makeCriteria(this.mode, key as CriterionType); + const criterion = makeCriteria( + this.mode, + key as CriterionType, + this.config + ); // it's possible that we have unsupported criteria. Just skip if so. if (criterion) { criterion.setFromEncodedCriterion(objectFilter[key]); diff --git a/ui/v2.5/src/models/list-filter/galleries.ts b/ui/v2.5/src/models/list-filter/galleries.ts index 2a597417f2a..693eb0ccb86 100644 --- a/ui/v2.5/src/models/list-filter/galleries.ts +++ b/ui/v2.5/src/models/list-filter/galleries.ts @@ -1,7 +1,6 @@ import { createMandatoryNumberCriterionOption, createStringCriterionOption, - NullNumberCriterionOption, createDateCriterionOption, createMandatoryTimestampCriterionOption, createPathCriterionOption, @@ -19,6 +18,7 @@ import { } from "./criteria/tags"; import { ListFilterOptions, MediaSortByOptions } from "./filter-options"; import { DisplayMode } from "./types"; +import { RatingCriterionOption } from "./criteria/rating"; const defaultSortBy = "path"; @@ -46,7 +46,7 @@ const criterionOptions = [ createStringCriterionOption("details"), createPathCriterionOption("path"), createStringCriterionOption("checksum", "media_info.checksum"), - new NullNumberCriterionOption("rating", "rating100"), + RatingCriterionOption, OrganizedCriterionOption, AverageResolutionCriterionOption, GalleryIsMissingCriterionOption, diff --git a/ui/v2.5/src/models/list-filter/images.ts b/ui/v2.5/src/models/list-filter/images.ts index 372ca21ca3e..3a54f34f46d 100644 --- a/ui/v2.5/src/models/list-filter/images.ts +++ b/ui/v2.5/src/models/list-filter/images.ts @@ -2,7 +2,6 @@ import { createMandatoryNumberCriterionOption, createMandatoryStringCriterionOption, createStringCriterionOption, - NullNumberCriterionOption, createMandatoryTimestampCriterionOption, createDateCriterionOption, createPathCriterionOption, @@ -11,6 +10,7 @@ import { PerformerFavoriteCriterionOption } from "./criteria/favorite"; import { ImageIsMissingCriterionOption } from "./criteria/is-missing"; import { OrganizedCriterionOption } from "./criteria/organized"; import { PerformersCriterionOption } from "./criteria/performers"; +import { RatingCriterionOption } from "./criteria/rating"; import { ResolutionCriterionOption } from "./criteria/resolution"; import { StudiosCriterionOption } from "./criteria/studios"; import { @@ -40,7 +40,7 @@ const criterionOptions = [ ResolutionCriterionOption, ImageIsMissingCriterionOption, TagsCriterionOption, - new NullNumberCriterionOption("rating", "rating100"), + RatingCriterionOption, createMandatoryNumberCriterionOption("tag_count"), PerformerTagsCriterionOption, PerformersCriterionOption, diff --git a/ui/v2.5/src/models/list-filter/movies.ts b/ui/v2.5/src/models/list-filter/movies.ts index be327abb4a0..3cc8f8da412 100644 --- a/ui/v2.5/src/models/list-filter/movies.ts +++ b/ui/v2.5/src/models/list-filter/movies.ts @@ -1,7 +1,6 @@ import { createMandatoryNumberCriterionOption, createStringCriterionOption, - NullNumberCriterionOption, createDateCriterionOption, createMandatoryTimestampCriterionOption, } from "./criteria/criterion"; @@ -10,6 +9,7 @@ import { StudiosCriterionOption } from "./criteria/studios"; import { PerformersCriterionOption } from "./criteria/performers"; import { ListFilterOptions } from "./filter-options"; import { DisplayMode } from "./types"; +import { RatingCriterionOption } from "./criteria/rating"; const defaultSortBy = "name"; @@ -30,7 +30,7 @@ const criterionOptions = [ createStringCriterionOption("director"), createStringCriterionOption("synopsis"), createMandatoryNumberCriterionOption("duration"), - new NullNumberCriterionOption("rating", "rating100"), + RatingCriterionOption, PerformersCriterionOption, createDateCriterionOption("date"), createMandatoryTimestampCriterionOption("created_at"), diff --git a/ui/v2.5/src/models/list-filter/performers.ts b/ui/v2.5/src/models/list-filter/performers.ts index 7c66880ee75..bf63bb59661 100644 --- a/ui/v2.5/src/models/list-filter/performers.ts +++ b/ui/v2.5/src/models/list-filter/performers.ts @@ -6,7 +6,6 @@ import { createDateCriterionOption, createMandatoryTimestampCriterionOption, NumberCriterionOption, - NullNumberCriterionOption, } from "./criteria/criterion"; import { FavoriteCriterionOption } from "./criteria/favorite"; import { GenderCriterionOption } from "./criteria/gender"; @@ -17,6 +16,8 @@ import { StudiosCriterionOption } from "./criteria/studios"; import { TagsCriterionOption } from "./criteria/tags"; import { ListFilterOptions } from "./filter-options"; import { CriterionType, DisplayMode } from "./types"; +import { CountryCriterionOption } from "./criteria/country"; +import { RatingCriterionOption } from "./criteria/rating"; const defaultSortBy = "name"; const sortByOptions = [ @@ -67,7 +68,6 @@ const stringCriteria: CriterionType[] = [ "disambiguation", "details", "ethnicity", - "country", "hair_color", "eye_color", "measurements", @@ -87,7 +87,7 @@ const criterionOptions = [ StudiosCriterionOption, StashIDCriterionOption, createStringCriterionOption("url"), - new NullNumberCriterionOption("rating", "rating100"), + RatingCriterionOption, createMandatoryNumberCriterionOption("tag_count"), createMandatoryNumberCriterionOption("scene_count"), createMandatoryNumberCriterionOption("image_count"), @@ -96,6 +96,7 @@ const criterionOptions = [ createBooleanCriterionOption("ignore_auto_tag"), new NumberCriterionOption("height", "height_cm"), ...numberCriteria.map((c) => createNumberCriterionOption(c)), + CountryCriterionOption, ...stringCriteria.map((c) => createStringCriterionOption(c)), createDateCriterionOption("birthdate"), createDateCriterionOption("death_date"), diff --git a/ui/v2.5/src/models/list-filter/scenes.ts b/ui/v2.5/src/models/list-filter/scenes.ts index 10895829849..5953b5f3982 100644 --- a/ui/v2.5/src/models/list-filter/scenes.ts +++ b/ui/v2.5/src/models/list-filter/scenes.ts @@ -2,7 +2,6 @@ import { createMandatoryNumberCriterionOption, createMandatoryStringCriterionOption, createStringCriterionOption, - NullNumberCriterionOption, createDateCriterionOption, createMandatoryTimestampCriterionOption, createPathCriterionOption, @@ -28,6 +27,7 @@ import { import { PerformerFavoriteCriterionOption } from "./criteria/favorite"; import { CaptionsCriterionOption } from "./criteria/captions"; import { StashIDCriterionOption } from "./criteria/stash-ids"; +import { RatingCriterionOption } from "./criteria/rating"; const defaultSortBy = "date"; const sortByOptions = [ @@ -68,7 +68,7 @@ const criterionOptions = [ PhashCriterionOption, DuplicatedCriterionOption, OrganizedCriterionOption, - new NullNumberCriterionOption("rating", "rating100"), + RatingCriterionOption, createMandatoryNumberCriterionOption("o_counter"), ResolutionCriterionOption, createStringCriterionOption("video_codec"), diff --git a/ui/v2.5/src/models/list-filter/studios.ts b/ui/v2.5/src/models/list-filter/studios.ts index 77b2d147310..e5e70aeec73 100644 --- a/ui/v2.5/src/models/list-filter/studios.ts +++ b/ui/v2.5/src/models/list-filter/studios.ts @@ -3,10 +3,10 @@ import { createMandatoryNumberCriterionOption, createMandatoryStringCriterionOption, createStringCriterionOption, - NullNumberCriterionOption, createMandatoryTimestampCriterionOption, } from "./criteria/criterion"; import { StudioIsMissingCriterionOption } from "./criteria/is-missing"; +import { RatingCriterionOption } from "./criteria/rating"; import { StashIDCriterionOption } from "./criteria/stash-ids"; import { ParentStudiosCriterionOption } from "./criteria/studios"; import { ListFilterOptions } from "./filter-options"; @@ -36,7 +36,7 @@ const criterionOptions = [ createStringCriterionOption("details"), ParentStudiosCriterionOption, StudioIsMissingCriterionOption, - new NullNumberCriterionOption("rating", "rating100"), + RatingCriterionOption, createBooleanCriterionOption("ignore_auto_tag"), createMandatoryNumberCriterionOption("scene_count"), createMandatoryNumberCriterionOption("image_count"),