From 9c460c6db7e6a4e7f8ed3e8d93032c7ef070efee Mon Sep 17 00:00:00 2001 From: Wolfgang Müller Date: Thu, 20 Feb 2025 13:40:40 +0100 Subject: Add filter for association counts This will replace the old 'empty' filter on comic associations and introduce a generic way of matching against association counts, along with support for different operators like 'greater than' or 'lower than'. Models that did not previously have a way of matching against their associates (like filtering for Artists that have N comics associated with them) now gain that functionality. For now the frontend keeps the simpler approach of allowing the user to only filter for empty associations, but we nonetheless need to adjust the 'empty' field to instead be linked to the new 'count' field. --- frontend/src/gql/graphql.ts | 25 +++++++++++++++++++++++-- frontend/src/lib/Enums.ts | 7 +++++++ frontend/src/lib/Filter.svelte.ts | 25 +++++++++++++++++++------ 3 files changed, 49 insertions(+), 8 deletions(-) (limited to 'frontend') diff --git a/frontend/src/gql/graphql.ts b/frontend/src/gql/graphql.ts index bd001f3..63f2c55 100644 --- a/frontend/src/gql/graphql.ts +++ b/frontend/src/gql/graphql.ts @@ -122,6 +122,7 @@ export type Artist = { }; export type ArtistFilter = { + comics?: InputMaybe; name?: InputMaybe; }; @@ -164,10 +165,14 @@ export type ArtistsUpsertInput = { export type AssociationFilter = { all?: InputMaybe>; any?: InputMaybe>; - empty?: InputMaybe; + count?: InputMaybe; exact?: InputMaybe>; }; +export type BasicCountFilter = { + count: CountFilter; +}; + export enum Category { Artbook = 'ARTBOOK', Comic = 'COMIC', @@ -203,6 +208,7 @@ export type Character = { }; export type CharacterFilter = { + comics?: InputMaybe; name?: InputMaybe; }; @@ -249,6 +255,7 @@ export type Circle = { }; export type CircleFilter = { + comics?: InputMaybe; name?: InputMaybe; }; @@ -396,6 +403,11 @@ export type ComicTotals = { worlds: Scalars['Int']['output']; }; +export type CountFilter = { + operator?: InputMaybe; + value: Scalars['Int']['input']; +}; + export type CoverInput = { id: Scalars['Int']['input']; }; @@ -862,6 +874,7 @@ export type Namespace = { export type NamespaceFilter = { name?: InputMaybe; + tags?: InputMaybe; }; export type NamespaceFilterInput = { @@ -905,6 +918,12 @@ export enum OnMissing { Ignore = 'IGNORE' } +export enum Operator { + Equal = 'EQUAL', + GreaterThan = 'GREATER_THAN', + LowerThan = 'LOWER_THAN' +} + export type Page = { __typename?: 'Page'; comicId?: Maybe; @@ -1153,11 +1172,12 @@ export type Tag = { export type TagAssociationFilter = { all?: InputMaybe>; any?: InputMaybe>; - empty?: InputMaybe; + count?: InputMaybe; exact?: InputMaybe>; }; export type TagFilter = { + comics?: InputMaybe; name?: InputMaybe; namespaces?: InputMaybe; }; @@ -1324,6 +1344,7 @@ export type World = { }; export type WorldFilter = { + comics?: InputMaybe; name?: InputMaybe; }; diff --git a/frontend/src/lib/Enums.ts b/frontend/src/lib/Enums.ts index 3264de4..db9fb86 100644 --- a/frontend/src/lib/Enums.ts +++ b/frontend/src/lib/Enums.ts @@ -10,6 +10,7 @@ import { Language, Layout, NamespaceSort, + Operator, Rating, TagSort, UpdateMode, @@ -125,6 +126,12 @@ export const UpdateModeLabel: Record = { [UpdateMode.Replace]: 'Replace' }; +export const OperatorLabel: Record = { + [Operator.Equal]: 'Equal', + [Operator.GreaterThan]: 'Greater than', + [Operator.LowerThan]: 'Lower than,' +}; + export const LanguageLabel: Record = { [Language.Ab]: 'Abkhazian', [Language.Aa]: 'Afar', diff --git a/frontend/src/lib/Filter.svelte.ts b/frontend/src/lib/Filter.svelte.ts index 6183f06..e73f497 100644 --- a/frontend/src/lib/Filter.svelte.ts +++ b/frontend/src/lib/Filter.svelte.ts @@ -1,4 +1,5 @@ import { + Operator, type ArchiveFilter, type ArchiveFilterInput, type ComicFilter, @@ -30,7 +31,7 @@ type AssocFilter = Filter< any?: T[] | null; all?: T[] | null; exact?: T[] | null; - empty?: boolean | null; + count?: { value: number; operator?: Operator | null } | null; }, K >; @@ -62,10 +63,6 @@ class ComplexMember { if (this.values.length > 0) { filter[this.key] = { [this.mode]: this.values }; } - - if (this.empty) { - filter[this.key] = { ...filter[this.key], empty: this.empty }; - } } } @@ -80,7 +77,9 @@ export class Association extends ComplexMember { } const prop = filter[key]; - this.empty = prop?.empty; + this.empty = + prop?.count?.value === 0 && + (prop.count.operator === undefined || prop.count.operator === Operator.Equal); if (prop?.all && prop.all.length > 0) { this.mode = 'all'; @@ -93,6 +92,13 @@ export class Association extends ComplexMember { this.values = prop.exact; } } + + integrate(filter: AssocFilter) { + super.integrate(filter); + if (this.empty) { + filter[this.key] = { ...filter[this.key], count: { value: 0, operator: Operator.Equal } }; + } + } } export class Enum extends ComplexMember { @@ -112,6 +118,13 @@ export class Enum extends ComplexMember { this.values = prop.any; } } + + integrate(filter: EnumFilter) { + super.integrate(filter); + if (this.empty) { + filter[this.key] = { ...filter[this.key], empty: this.empty }; + } + } } class Bool { -- cgit v1.2.3-2-gb3c3