From 3e3e8b95e2bcb95df604ac4d42d9dd541d676db2 Mon Sep 17 00:00:00 2001 From: bob123491234 <54259225+bob123491234@users.noreply.github.com> Date: Sun, 19 May 2024 22:04:45 -0500 Subject: [PATCH] Add scenes filter to galleries (#4840) --- graphql/schema/types/filters.graphql | 2 ++ pkg/models/gallery.go | 2 ++ .../stashbox/graphql/generated_models.go | 2 +- pkg/sqlite/gallery.go | 21 +++++++++++++++++++ .../List/Filters/LabeledIdFilter.tsx | 1 + ui/v2.5/src/components/Shared/Select.tsx | 3 +++ .../models/list-filter/criteria/criterion.ts | 1 + .../src/models/list-filter/criteria/scenes.ts | 17 +++++++++++++++ ui/v2.5/src/models/list-filter/galleries.ts | 2 ++ ui/v2.5/src/models/list-filter/types.ts | 1 + 10 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 ui/v2.5/src/models/list-filter/criteria/scenes.ts diff --git a/graphql/schema/types/filters.graphql b/graphql/schema/types/filters.graphql index 2f80b8b02..443da9b07 100644 --- a/graphql/schema/types/filters.graphql +++ b/graphql/schema/types/filters.graphql @@ -378,6 +378,8 @@ input GalleryFilterType { average_resolution: ResolutionCriterionInput "Filter to only include galleries that have chapters. `true` or `false`" has_chapters: String + "Filter to only include galleries with these scenes" + scenes: MultiCriterionInput "Filter to only include galleries with this studio" studios: HierarchicalMultiCriterionInput "Filter to only include galleries with these tags" diff --git a/pkg/models/gallery.go b/pkg/models/gallery.go index 02e492876..0145ff5e6 100644 --- a/pkg/models/gallery.go +++ b/pkg/models/gallery.go @@ -27,6 +27,8 @@ type GalleryFilterType struct { AverageResolution *ResolutionCriterionInput `json:"average_resolution"` // Filter to only include scenes which have chapters. `true` or `false` HasChapters *string `json:"has_chapters"` + // Filter to only include galleries with these scenes + Scenes *MultiCriterionInput `json:"scenes"` // Filter to only include galleries with this studio Studios *HierarchicalMultiCriterionInput `json:"studios"` // Filter to only include galleries with these tags diff --git a/pkg/scraper/stashbox/graphql/generated_models.go b/pkg/scraper/stashbox/graphql/generated_models.go index 061053c7d..87f99db47 100644 --- a/pkg/scraper/stashbox/graphql/generated_models.go +++ b/pkg/scraper/stashbox/graphql/generated_models.go @@ -1034,7 +1034,7 @@ type TagQueryInput struct { // Filter to search name - assumes like query unless quoted Name *string `json:"name,omitempty"` // Filter to category ID - IsFavorite *bool `json:"is_favorite,omitempty"` + IsFavorite *bool `json:"is_favorite,omitempty"` CategoryID *string `json:"category_id,omitempty"` Page int `json:"page"` PerPage int `json:"per_page"` diff --git a/pkg/sqlite/gallery.go b/pkg/sqlite/gallery.go index 1c9e1cf7e..61ade6e6f 100644 --- a/pkg/sqlite/gallery.go +++ b/pkg/sqlite/gallery.go @@ -699,6 +699,7 @@ func (qb *GalleryStore) makeFilter(ctx context.Context, galleryFilter *models.Ga query.handleCriterion(ctx, galleryPerformersCriterionHandler(qb, galleryFilter.Performers)) query.handleCriterion(ctx, galleryPerformerCountCriterionHandler(qb, galleryFilter.PerformerCount)) query.handleCriterion(ctx, hasChaptersCriterionHandler(galleryFilter.HasChapters)) + query.handleCriterion(ctx, galleryScenesCriterionHandler(qb, galleryFilter.Scenes)) query.handleCriterion(ctx, studioCriterionHandler(galleryTable, galleryFilter.Studios)) query.handleCriterion(ctx, galleryPerformerTagsCriterionHandler(qb, galleryFilter.PerformerTags)) query.handleCriterion(ctx, galleryAverageResolutionCriterionHandler(qb, galleryFilter.AverageResolution)) @@ -827,6 +828,17 @@ func galleryURLsCriterionHandler(url *models.StringCriterionInput) criterionHand return h.handler(url) } +func (qb *GalleryStore) getMultiCriterionHandlerBuilder(foreignTable, joinTable, foreignFK string, addJoinsFunc func(f *filterBuilder)) multiCriterionHandlerBuilder { + return multiCriterionHandlerBuilder{ + primaryTable: galleryTable, + foreignTable: foreignTable, + joinTable: joinTable, + primaryFK: galleryIDColumn, + foreignFK: foreignFK, + addJoinsFunc: addJoinsFunc, + } +} + func (qb *GalleryStore) galleryPathCriterionHandler(c *models.StringCriterionInput) criterionHandlerFunc { return func(ctx context.Context, f *filterBuilder) { if c != nil { @@ -958,6 +970,15 @@ func galleryTagCountCriterionHandler(qb *GalleryStore, tagCount *models.IntCrite return h.handler(tagCount) } +func galleryScenesCriterionHandler(qb *GalleryStore, scenes *models.MultiCriterionInput) criterionHandlerFunc { + addJoinsFunc := func(f *filterBuilder) { + qb.scenesRepository().join(f, "", "galleries.id") + f.addLeftJoin("scenes", "", "scenes_galleries.scene_id = scenes.id") + } + h := qb.getMultiCriterionHandlerBuilder(sceneTable, galleriesScenesTable, "scene_id", addJoinsFunc) + return h.handler(scenes) +} + func galleryPerformersCriterionHandler(qb *GalleryStore, performers *models.MultiCriterionInput) criterionHandlerFunc { h := joinedMultiCriterionHandlerBuilder{ primaryTable: galleryTable, diff --git a/ui/v2.5/src/components/List/Filters/LabeledIdFilter.tsx b/ui/v2.5/src/components/List/Filters/LabeledIdFilter.tsx index c2fa322f8..78f271c0f 100644 --- a/ui/v2.5/src/components/List/Filters/LabeledIdFilter.tsx +++ b/ui/v2.5/src/components/List/Filters/LabeledIdFilter.tsx @@ -23,6 +23,7 @@ export const LabeledIdFilter: React.FC = ({ inputType !== "scene_tags" && inputType !== "performer_tags" && inputType !== "tags" && + inputType !== "scenes" && inputType !== "movies" && inputType !== "galleries" ) { diff --git a/ui/v2.5/src/components/Shared/Select.tsx b/ui/v2.5/src/components/Shared/Select.tsx index 71724c74e..201bb5a3d 100644 --- a/ui/v2.5/src/components/Shared/Select.tsx +++ b/ui/v2.5/src/components/Shared/Select.tsx @@ -43,6 +43,7 @@ interface ITypeProps { | "tags" | "scene_tags" | "performer_tags" + | "scenes" | "movies" | "galleries"; } @@ -379,6 +380,8 @@ export const FilterSelect: React.FC = (props) => { return ; case "studios": return ; + case "scenes": + return ; case "movies": return ; case "galleries": 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 a2a4c8c4b..90874b70a 100644 --- a/ui/v2.5/src/models/list-filter/criteria/criterion.ts +++ b/ui/v2.5/src/models/list-filter/criteria/criterion.ts @@ -171,6 +171,7 @@ export type InputType = | "studios" | "tags" | "performer_tags" + | "scenes" | "scene_tags" | "movies" | "galleries" diff --git a/ui/v2.5/src/models/list-filter/criteria/scenes.ts b/ui/v2.5/src/models/list-filter/criteria/scenes.ts new file mode 100644 index 000000000..365cc7f86 --- /dev/null +++ b/ui/v2.5/src/models/list-filter/criteria/scenes.ts @@ -0,0 +1,17 @@ +import { ILabeledIdCriterion, ILabeledIdCriterionOption } from "./criterion"; + +const inputType = "scenes"; + +export const ScenesCriterionOption = new ILabeledIdCriterionOption( + "scenes", + "scenes", + true, + inputType, + () => new ScenesCriterion() +); + +export class ScenesCriterion extends ILabeledIdCriterion { + constructor() { + super(ScenesCriterionOption); + } +} diff --git a/ui/v2.5/src/models/list-filter/galleries.ts b/ui/v2.5/src/models/list-filter/galleries.ts index 720837c11..8c1fc5a76 100644 --- a/ui/v2.5/src/models/list-filter/galleries.ts +++ b/ui/v2.5/src/models/list-filter/galleries.ts @@ -10,6 +10,7 @@ import { OrganizedCriterionOption } from "./criteria/organized"; import { HasChaptersCriterionOption } from "./criteria/has-chapters"; import { PerformersCriterionOption } from "./criteria/performers"; import { AverageResolutionCriterionOption } from "./criteria/resolution"; +import { ScenesCriterionOption } from "./criteria/scenes"; import { StudiosCriterionOption } from "./criteria/studios"; import { PerformerTagsCriterionOption, @@ -61,6 +62,7 @@ const criterionOptions = [ createMandatoryNumberCriterionOption("performer_age"), PerformerFavoriteCriterionOption, createMandatoryNumberCriterionOption("image_count"), + ScenesCriterionOption, StudiosCriterionOption, createStringCriterionOption("url"), createMandatoryNumberCriterionOption("file_count", "zip_file_count"), diff --git a/ui/v2.5/src/models/list-filter/types.ts b/ui/v2.5/src/models/list-filter/types.ts index 739e3248b..4a0c49e17 100644 --- a/ui/v2.5/src/models/list-filter/types.ts +++ b/ui/v2.5/src/models/list-filter/types.ts @@ -145,6 +145,7 @@ export type CriterionType = | "tag_count" | "performers" | "studios" + | "scenes" | "movies" | "galleries" | "birth_year"