diff --git a/graphql/schema/types/filters.graphql b/graphql/schema/types/filters.graphql index 23396a98ffd..5f2e8a83c66 100644 --- a/graphql/schema/types/filters.graphql +++ b/graphql/schema/types/filters.graphql @@ -230,6 +230,8 @@ input SceneFilterType { phash_distance: PhashDistanceCriterionInput "Filter by path" path: StringCriterionInput + "Filter by filename/basename" + filename: StringCriterionInput "Filter by file count" file_count: IntCriterionInput # rating expressed as 1-100 @@ -613,6 +615,8 @@ input ImageFilterType { checksum: StringCriterionInput "Filter by path" path: StringCriterionInput + "Filter by filename/basename" + filename: StringCriterionInput "Filter by file count" file_count: IntCriterionInput # rating expressed as 1-100 diff --git a/pkg/models/image.go b/pkg/models/image.go index 6026070fadf..c0c27718ec4 100644 --- a/pkg/models/image.go +++ b/pkg/models/image.go @@ -13,6 +13,8 @@ type ImageFilterType struct { Checksum *StringCriterionInput `json:"checksum"` // Filter by path Path *StringCriterionInput `json:"path"` + // Filter by filename/basename + Filename *StringCriterionInput `json:"filename"` // Filter by file count FileCount *IntCriterionInput `json:"file_count"` // Filter by rating expressed as 1-100 diff --git a/pkg/models/scene.go b/pkg/models/scene.go index c7be343d98c..344cb578988 100644 --- a/pkg/models/scene.go +++ b/pkg/models/scene.go @@ -25,6 +25,8 @@ type SceneFilterType struct { PhashDistance *PhashDistanceCriterionInput `json:"phash_distance"` // Filter by path Path *StringCriterionInput `json:"path"` + // Filter by filename/basename + Filename *StringCriterionInput `json:"filename"` // Filter by file count FileCount *IntCriterionInput `json:"file_count"` // Filter by rating expressed as 1-100 diff --git a/pkg/sqlite/criterion_handlers.go b/pkg/sqlite/criterion_handlers.go index 55ff31fca82..0f2f57a5ea6 100644 --- a/pkg/sqlite/criterion_handlers.go +++ b/pkg/sqlite/criterion_handlers.go @@ -93,6 +93,17 @@ func enumCriterionHandler(modifier models.CriterionModifier, values []string, co } } +func filenameCriterionHandler(c *models.StringCriterionInput, basenameColumn string, addJoinFn func(f *filterBuilder)) criterionHandlerFunc { + return func(ctx context.Context, f *filterBuilder) { + if c != nil { + if addJoinFn != nil { + addJoinFn(f) + } + stringCriterionHandler(c, basenameColumn)(ctx, f) + } + } +} + func pathCriterionHandler(c *models.StringCriterionInput, pathColumn string, basenameColumn string, addJoinFn func(f *filterBuilder)) criterionHandlerFunc { return func(ctx context.Context, f *filterBuilder) { if c != nil { diff --git a/pkg/sqlite/image_filter.go b/pkg/sqlite/image_filter.go index 8f2d5d6b90a..9789e47e7be 100644 --- a/pkg/sqlite/image_filter.go +++ b/pkg/sqlite/image_filter.go @@ -68,6 +68,7 @@ func (qb *imageFilterHandler) criterionHandler() criterionHandler { stringCriterionHandler(imageFilter.Photographer, "images.photographer"), pathCriterionHandler(imageFilter.Path, "folders.path", "files.basename", imageRepository.addFoldersTable), + filenameCriterionHandler(imageFilter.Filename, "files.basename", imageRepository.addImagesFilesTable), qb.fileCountCriterionHandler(imageFilter.FileCount), intCriterionHandler(imageFilter.Rating100, "images.rating", nil), intCriterionHandler(imageFilter.OCounter, "images.o_counter", nil), diff --git a/pkg/sqlite/scene_filter.go b/pkg/sqlite/scene_filter.go index 2e63dad975f..037b6dc7ad1 100644 --- a/pkg/sqlite/scene_filter.go +++ b/pkg/sqlite/scene_filter.go @@ -57,6 +57,7 @@ func (qb *sceneFilterHandler) criterionHandler() criterionHandler { return compoundHandler{ intCriterionHandler(sceneFilter.ID, "scenes.id", nil), pathCriterionHandler(sceneFilter.Path, "folders.path", "files.basename", qb.addFoldersTable), + filenameCriterionHandler(sceneFilter.Filename, "files.basename", qb.addFilesTable), qb.fileCountCriterionHandler(sceneFilter.FileCount), stringCriterionHandler(sceneFilter.Title, "scenes.title"), stringCriterionHandler(sceneFilter.Code, "scenes.code"), @@ -383,8 +384,8 @@ func (qb *sceneFilterHandler) captionCriterionHandler(captions *models.StringCri }, excludeHandler: func(f *filterBuilder, criterion *models.StringCriterionInput) { excludeClause := `scenes.id NOT IN ( - SELECT scenes_files.scene_id from scenes_files - INNER JOIN video_captions on video_captions.file_id = scenes_files.file_id + SELECT scenes_files.scene_id from scenes_files + INNER JOIN video_captions on video_captions.file_id = scenes_files.file_id WHERE video_captions.language_code LIKE ? )` f.addWhere(excludeClause, criterion.Value) diff --git a/ui/v2.5/src/models/list-filter/images.ts b/ui/v2.5/src/models/list-filter/images.ts index d8619112df6..33a72f7290b 100644 --- a/ui/v2.5/src/models/list-filter/images.ts +++ b/ui/v2.5/src/models/list-filter/images.ts @@ -41,6 +41,10 @@ const criterionOptions = [ createStringCriterionOption("photographer"), createMandatoryStringCriterionOption("checksum", "media_info.checksum"), PathCriterionOption, + createStringCriterionOption( + "filename", + "component_tagger.config.query_mode_filename" + ), GalleriesCriterionOption, OrganizedCriterionOption, createMandatoryNumberCriterionOption("o_counter", "o_count"), diff --git a/ui/v2.5/src/models/list-filter/scenes.ts b/ui/v2.5/src/models/list-filter/scenes.ts index 7496da6b62d..de7ec4a6023 100644 --- a/ui/v2.5/src/models/list-filter/scenes.ts +++ b/ui/v2.5/src/models/list-filter/scenes.ts @@ -77,6 +77,10 @@ const criterionOptions = [ createStringCriterionOption("title"), createStringCriterionOption("code", "scene_code"), PathCriterionOption, + createStringCriterionOption( + "filename", + "component_tagger.config.query_mode_filename" + ), createStringCriterionOption("details"), createStringCriterionOption("director"), createMandatoryStringCriterionOption("oshash", "media_info.hash"), diff --git a/ui/v2.5/src/models/list-filter/types.ts b/ui/v2.5/src/models/list-filter/types.ts index 48e37c0461d..54379de7dc6 100644 --- a/ui/v2.5/src/models/list-filter/types.ts +++ b/ui/v2.5/src/models/list-filter/types.ts @@ -125,6 +125,7 @@ export interface IOptionType { export type CriterionType = | "path" + | "filename" | "rating100" | "organized" | "o_counter"