mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 04:44:37 +03:00
[Files Refactor] Filter and sort by file count (#2744)
* Add filtering on file count * Add sorting by file count
This commit is contained in:
@@ -132,6 +132,8 @@ input SceneFilterType {
|
|||||||
phash: StringCriterionInput
|
phash: StringCriterionInput
|
||||||
"""Filter by path"""
|
"""Filter by path"""
|
||||||
path: StringCriterionInput
|
path: StringCriterionInput
|
||||||
|
"""Filter by file count"""
|
||||||
|
file_count: IntCriterionInput
|
||||||
"""Filter by rating"""
|
"""Filter by rating"""
|
||||||
rating: IntCriterionInput
|
rating: IntCriterionInput
|
||||||
"""Filter by organized"""
|
"""Filter by organized"""
|
||||||
@@ -239,6 +241,8 @@ input GalleryFilterType {
|
|||||||
checksum: StringCriterionInput
|
checksum: StringCriterionInput
|
||||||
"""Filter by path"""
|
"""Filter by path"""
|
||||||
path: StringCriterionInput
|
path: StringCriterionInput
|
||||||
|
"""Filter by zip-file count"""
|
||||||
|
file_count: IntCriterionInput
|
||||||
"""Filter to only include galleries missing this property"""
|
"""Filter to only include galleries missing this property"""
|
||||||
is_missing: String
|
is_missing: String
|
||||||
"""Filter to include/exclude galleries that were created from zip"""
|
"""Filter to include/exclude galleries that were created from zip"""
|
||||||
@@ -327,6 +331,8 @@ input ImageFilterType {
|
|||||||
checksum: StringCriterionInput
|
checksum: StringCriterionInput
|
||||||
"""Filter by path"""
|
"""Filter by path"""
|
||||||
path: StringCriterionInput
|
path: StringCriterionInput
|
||||||
|
"""Filter by file count"""
|
||||||
|
file_count: IntCriterionInput
|
||||||
"""Filter by rating"""
|
"""Filter by rating"""
|
||||||
rating: IntCriterionInput
|
rating: IntCriterionInput
|
||||||
"""Filter by organized"""
|
"""Filter by organized"""
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ type GalleryFilterType struct {
|
|||||||
Checksum *StringCriterionInput `json:"checksum"`
|
Checksum *StringCriterionInput `json:"checksum"`
|
||||||
// Filter by path
|
// Filter by path
|
||||||
Path *StringCriterionInput `json:"path"`
|
Path *StringCriterionInput `json:"path"`
|
||||||
|
// Filter by zip file count
|
||||||
|
FileCount *IntCriterionInput `json:"file_count"`
|
||||||
// Filter to only include galleries missing this property
|
// Filter to only include galleries missing this property
|
||||||
IsMissing *string `json:"is_missing"`
|
IsMissing *string `json:"is_missing"`
|
||||||
// Filter to include/exclude galleries that were created from zip
|
// Filter to include/exclude galleries that were created from zip
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ type ImageFilterType struct {
|
|||||||
Checksum *StringCriterionInput `json:"checksum"`
|
Checksum *StringCriterionInput `json:"checksum"`
|
||||||
// Filter by path
|
// Filter by path
|
||||||
Path *StringCriterionInput `json:"path"`
|
Path *StringCriterionInput `json:"path"`
|
||||||
|
// Filter by file count
|
||||||
|
FileCount *IntCriterionInput `json:"file_count"`
|
||||||
// Filter by rating
|
// Filter by rating
|
||||||
Rating *IntCriterionInput `json:"rating"`
|
Rating *IntCriterionInput `json:"rating"`
|
||||||
// Filter by organized
|
// Filter by organized
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ type SceneFilterType struct {
|
|||||||
Phash *StringCriterionInput `json:"phash"`
|
Phash *StringCriterionInput `json:"phash"`
|
||||||
// Filter by path
|
// Filter by path
|
||||||
Path *StringCriterionInput `json:"path"`
|
Path *StringCriterionInput `json:"path"`
|
||||||
|
// Filter by file count
|
||||||
|
FileCount *IntCriterionInput `json:"file_count"`
|
||||||
// Filter by rating
|
// Filter by rating
|
||||||
Rating *IntCriterionInput `json:"rating"`
|
Rating *IntCriterionInput `json:"rating"`
|
||||||
// Filter by organized
|
// Filter by organized
|
||||||
|
|||||||
@@ -596,6 +596,7 @@ func (qb *GalleryStore) makeFilter(ctx context.Context, galleryFilter *models.Ga
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
query.handleCriterion(ctx, pathCriterionHandler(galleryFilter.Path, "galleries_query.parent_folder_path", "galleries_query.basename"))
|
query.handleCriterion(ctx, pathCriterionHandler(galleryFilter.Path, "galleries_query.parent_folder_path", "galleries_query.basename"))
|
||||||
|
query.handleCriterion(ctx, galleryFileCountCriterionHandler(qb, galleryFilter.FileCount))
|
||||||
query.handleCriterion(ctx, intCriterionHandler(galleryFilter.Rating, "galleries.rating"))
|
query.handleCriterion(ctx, intCriterionHandler(galleryFilter.Rating, "galleries.rating"))
|
||||||
query.handleCriterion(ctx, stringCriterionHandler(galleryFilter.URL, "galleries.url"))
|
query.handleCriterion(ctx, stringCriterionHandler(galleryFilter.URL, "galleries.url"))
|
||||||
query.handleCriterion(ctx, boolCriterionHandler(galleryFilter.Organized, "galleries.organized"))
|
query.handleCriterion(ctx, boolCriterionHandler(galleryFilter.Organized, "galleries.organized"))
|
||||||
@@ -683,6 +684,16 @@ func (qb *GalleryStore) QueryCount(ctx context.Context, galleryFilter *models.Ga
|
|||||||
return query.executeCount(ctx)
|
return query.executeCount(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func galleryFileCountCriterionHandler(qb *GalleryStore, fileCount *models.IntCriterionInput) criterionHandlerFunc {
|
||||||
|
h := countCriterionHandlerBuilder{
|
||||||
|
primaryTable: galleryTable,
|
||||||
|
joinTable: galleriesFilesTable,
|
||||||
|
primaryFK: galleryIDColumn,
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.handler(fileCount)
|
||||||
|
}
|
||||||
|
|
||||||
func galleryIsMissingCriterionHandler(qb *GalleryStore, isMissing *string) criterionHandlerFunc {
|
func galleryIsMissingCriterionHandler(qb *GalleryStore, isMissing *string) criterionHandlerFunc {
|
||||||
return func(ctx context.Context, f *filterBuilder) {
|
return func(ctx context.Context, f *filterBuilder) {
|
||||||
if isMissing != nil && *isMissing != "" {
|
if isMissing != nil && *isMissing != "" {
|
||||||
@@ -897,6 +908,8 @@ func (qb *GalleryStore) getGallerySort(findFilter *models.FindFilterType) string
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch sort {
|
switch sort {
|
||||||
|
case "file_count":
|
||||||
|
return getCountSort(galleryTable, galleriesFilesTable, galleryIDColumn, direction)
|
||||||
case "images_count":
|
case "images_count":
|
||||||
return getCountSort(galleryTable, galleriesImagesTable, galleryIDColumn, direction)
|
return getCountSort(galleryTable, galleriesImagesTable, galleryIDColumn, direction)
|
||||||
case "tag_count":
|
case "tag_count":
|
||||||
|
|||||||
@@ -564,6 +564,7 @@ func (qb *ImageStore) makeFilter(ctx context.Context, imageFilter *models.ImageF
|
|||||||
query.handleCriterion(ctx, stringCriterionHandler(imageFilter.Title, "images.title"))
|
query.handleCriterion(ctx, stringCriterionHandler(imageFilter.Title, "images.title"))
|
||||||
|
|
||||||
query.handleCriterion(ctx, pathCriterionHandler(imageFilter.Path, "images_query.parent_folder_path", "images_query.basename"))
|
query.handleCriterion(ctx, pathCriterionHandler(imageFilter.Path, "images_query.parent_folder_path", "images_query.basename"))
|
||||||
|
query.handleCriterion(ctx, imageFileCountCriterionHandler(qb, imageFilter.FileCount))
|
||||||
query.handleCriterion(ctx, intCriterionHandler(imageFilter.Rating, "images.rating"))
|
query.handleCriterion(ctx, intCriterionHandler(imageFilter.Rating, "images.rating"))
|
||||||
query.handleCriterion(ctx, intCriterionHandler(imageFilter.OCounter, "images.o_counter"))
|
query.handleCriterion(ctx, intCriterionHandler(imageFilter.OCounter, "images.o_counter"))
|
||||||
query.handleCriterion(ctx, boolCriterionHandler(imageFilter.Organized, "images.organized"))
|
query.handleCriterion(ctx, boolCriterionHandler(imageFilter.Organized, "images.organized"))
|
||||||
@@ -689,6 +690,16 @@ func (qb *ImageStore) QueryCount(ctx context.Context, imageFilter *models.ImageF
|
|||||||
return query.executeCount(ctx)
|
return query.executeCount(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func imageFileCountCriterionHandler(qb *ImageStore, fileCount *models.IntCriterionInput) criterionHandlerFunc {
|
||||||
|
h := countCriterionHandlerBuilder{
|
||||||
|
primaryTable: imageTable,
|
||||||
|
joinTable: imagesFilesTable,
|
||||||
|
primaryFK: imageIDColumn,
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.handler(fileCount)
|
||||||
|
}
|
||||||
|
|
||||||
func imageIsMissingCriterionHandler(qb *ImageStore, isMissing *string) criterionHandlerFunc {
|
func imageIsMissingCriterionHandler(qb *ImageStore, isMissing *string) criterionHandlerFunc {
|
||||||
return func(ctx context.Context, f *filterBuilder) {
|
return func(ctx context.Context, f *filterBuilder) {
|
||||||
if isMissing != nil && *isMissing != "" {
|
if isMissing != nil && *isMissing != "" {
|
||||||
@@ -869,6 +880,8 @@ func (qb *ImageStore) getImageSort(findFilter *models.FindFilterType) string {
|
|||||||
switch sort {
|
switch sort {
|
||||||
case "path":
|
case "path":
|
||||||
return " ORDER BY images_query.parent_folder_path " + direction + ", images_query.basename " + direction
|
return " ORDER BY images_query.parent_folder_path " + direction + ", images_query.basename " + direction
|
||||||
|
case "file_count":
|
||||||
|
return getCountSort(imageTable, imagesFilesTable, imageIDColumn, direction)
|
||||||
case "tag_count":
|
case "tag_count":
|
||||||
return getCountSort(imageTable, imagesTagsTable, imageIDColumn, direction)
|
return getCountSort(imageTable, imagesTagsTable, imageIDColumn, direction)
|
||||||
case "performer_count":
|
case "performer_count":
|
||||||
|
|||||||
@@ -756,6 +756,7 @@ func (qb *SceneStore) makeFilter(ctx context.Context, sceneFilter *models.SceneF
|
|||||||
}
|
}
|
||||||
|
|
||||||
query.handleCriterion(ctx, pathCriterionHandler(sceneFilter.Path, "scenes_query.parent_folder_path", "scenes_query.basename"))
|
query.handleCriterion(ctx, pathCriterionHandler(sceneFilter.Path, "scenes_query.parent_folder_path", "scenes_query.basename"))
|
||||||
|
query.handleCriterion(ctx, sceneFileCountCriterionHandler(qb, sceneFilter.FileCount))
|
||||||
query.handleCriterion(ctx, stringCriterionHandler(sceneFilter.Title, "scenes.title"))
|
query.handleCriterion(ctx, stringCriterionHandler(sceneFilter.Title, "scenes.title"))
|
||||||
query.handleCriterion(ctx, stringCriterionHandler(sceneFilter.Details, "scenes.details"))
|
query.handleCriterion(ctx, stringCriterionHandler(sceneFilter.Details, "scenes.details"))
|
||||||
query.handleCriterion(ctx, criterionHandlerFunc(func(ctx context.Context, f *filterBuilder) {
|
query.handleCriterion(ctx, criterionHandlerFunc(func(ctx context.Context, f *filterBuilder) {
|
||||||
@@ -916,6 +917,16 @@ func (qb *SceneStore) queryGroupedFields(ctx context.Context, options models.Sce
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sceneFileCountCriterionHandler(qb *SceneStore, fileCount *models.IntCriterionInput) criterionHandlerFunc {
|
||||||
|
h := countCriterionHandlerBuilder{
|
||||||
|
primaryTable: sceneTable,
|
||||||
|
joinTable: scenesFilesTable,
|
||||||
|
primaryFK: sceneIDColumn,
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.handler(fileCount)
|
||||||
|
}
|
||||||
|
|
||||||
func scenePhashDuplicatedCriterionHandler(duplicatedFilter *models.PHashDuplicationCriterionInput) criterionHandlerFunc {
|
func scenePhashDuplicatedCriterionHandler(duplicatedFilter *models.PHashDuplicationCriterionInput) criterionHandlerFunc {
|
||||||
return func(ctx context.Context, f *filterBuilder) {
|
return func(ctx context.Context, f *filterBuilder) {
|
||||||
// TODO: Wishlist item: Implement Distance matching
|
// TODO: Wishlist item: Implement Distance matching
|
||||||
@@ -1204,6 +1215,8 @@ func (qb *SceneStore) setSceneSort(query *queryBuilder, findFilter *models.FindF
|
|||||||
query.sortAndPagination += getCountSort(sceneTable, scenesTagsTable, sceneIDColumn, direction)
|
query.sortAndPagination += getCountSort(sceneTable, scenesTagsTable, sceneIDColumn, direction)
|
||||||
case "performer_count":
|
case "performer_count":
|
||||||
query.sortAndPagination += getCountSort(sceneTable, performersScenesTable, sceneIDColumn, direction)
|
query.sortAndPagination += getCountSort(sceneTable, performersScenesTable, sceneIDColumn, direction)
|
||||||
|
case "file_count":
|
||||||
|
query.sortAndPagination += getCountSort(sceneTable, scenesFilesTable, sceneIDColumn, direction)
|
||||||
case "path":
|
case "path":
|
||||||
// special handling for path
|
// special handling for path
|
||||||
query.sortAndPagination += fmt.Sprintf(" ORDER BY scenes_query.parent_folder_path %s, scenes_query.basename %[1]s", direction)
|
query.sortAndPagination += fmt.Sprintf(" ORDER BY scenes_query.parent_folder_path %s, scenes_query.basename %[1]s", direction)
|
||||||
|
|||||||
@@ -7,14 +7,15 @@ After migrating, please run a scan on your entire library to populate missing da
|
|||||||
Please report all issues to the following Github issue: https://github.com/stashapp/stash/issues/2737
|
Please report all issues to the following Github issue: https://github.com/stashapp/stash/issues/2737
|
||||||
|
|
||||||
### 💥 Known issues
|
### 💥 Known issues
|
||||||
* import/export functionality is currently disabled. Needs further design.
|
* Import/export functionality is currently disabled. Needs further design.
|
||||||
* missing covers are not currently regenerated. Need to consider further, especially around scene cover redesign.
|
* Missing covers are not currently regenerated. Need to consider further, especially around scene cover redesign.
|
||||||
* deleting galleries is currently slow.
|
* Deleting galleries is currently slow.
|
||||||
* Don't include file extension as part of the title scan flag is not supported.
|
* Don't include file extension as part of the title scan flag is not supported.
|
||||||
* Set name, date, details from embedded file metadata scan flag is not supported.
|
* Set name, date, details from embedded file metadata scan flag is not supported.
|
||||||
|
|
||||||
### ✨ New Features
|
### ✨ New Features
|
||||||
* Added support for identical files. Identical files are assigned to the same scene/gallery/image and can be viewed in File Info. ([#2676](https://github.com/stashapp/stash/pull/2676))
|
* Added support for identical files. Identical files are assigned to the same scene/gallery/image and can be viewed in File Info. ([#2676](https://github.com/stashapp/stash/pull/2676))
|
||||||
|
* Added support for filtering and sorting by file count. ([#2744](https://github.com/stashapp/stash/pull/2744))
|
||||||
* Added release notes dialog. ([#2726](https://github.com/stashapp/stash/pull/2726))
|
* Added release notes dialog. ([#2726](https://github.com/stashapp/stash/pull/2726))
|
||||||
|
|
||||||
### 🎨 Improvements
|
### 🎨 Improvements
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ interface IReleaseNotes {
|
|||||||
|
|
||||||
export const releaseNotes: IReleaseNotes[] = [
|
export const releaseNotes: IReleaseNotes[] = [
|
||||||
{
|
{
|
||||||
date: 20220707,
|
date: 20220715,
|
||||||
content: v0170,
|
content: v0170,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ After migrating, please run a scan on your entire library to populate missing da
|
|||||||
Please report all issues to the following Github issue: https://github.com/stashapp/stash/issues/2737
|
Please report all issues to the following Github issue: https://github.com/stashapp/stash/issues/2737
|
||||||
|
|
||||||
### 💥 Known issues
|
### 💥 Known issues
|
||||||
* import/export functionality is currently disabled. Needs further design.
|
* Import/export functionality is currently disabled. Needs further design.
|
||||||
* missing covers are not currently regenerated. Need to consider further, especially around scene cover redesign.
|
* Missing covers are not currently regenerated. Need to consider further, especially around scene cover redesign.
|
||||||
* deleting galleries is currently slow.
|
* Deleting galleries is currently slow.
|
||||||
* Don't include file extension as part of the title scan flag is not supported.
|
* Don't include file extension as part of the title scan flag is not supported.
|
||||||
* Set name, date, details from embedded file metadata scan flag is not supported.
|
* Set name, date, details from embedded file metadata scan flag is not supported.
|
||||||
|
|
||||||
### Other changes:
|
### Other changes:
|
||||||
|
|
||||||
|
* Added support for filtering and sorting by file count. ([#2744](https://github.com/stashapp/stash/pull/2744))
|
||||||
* Changelog has been moved from the stats page to a section in the Settings page.
|
* Changelog has been moved from the stats page to a section in the Settings page.
|
||||||
@@ -728,6 +728,7 @@
|
|||||||
"false": "False",
|
"false": "False",
|
||||||
"favourite": "Favourite",
|
"favourite": "Favourite",
|
||||||
"file": "file",
|
"file": "file",
|
||||||
|
"file_count": "File Count",
|
||||||
"file_info": "File Info",
|
"file_info": "File Info",
|
||||||
"file_mod_time": "File Modification Time",
|
"file_mod_time": "File Modification Time",
|
||||||
"files": "files",
|
"files": "files",
|
||||||
@@ -1024,5 +1025,6 @@
|
|||||||
"videos": "Videos",
|
"videos": "Videos",
|
||||||
"view_all": "View All",
|
"view_all": "View All",
|
||||||
"weight": "Weight",
|
"weight": "Weight",
|
||||||
"years_old": "years old"
|
"years_old": "years old",
|
||||||
|
"zip_file_count": "Zip File Count"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -497,8 +497,11 @@ export class MandatoryNumberCriterionOption extends CriterionOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createMandatoryNumberCriterionOption(value: CriterionType) {
|
export function createMandatoryNumberCriterionOption(
|
||||||
return new MandatoryNumberCriterionOption(value, value, value);
|
value: CriterionType,
|
||||||
|
messageID?: string
|
||||||
|
) {
|
||||||
|
return new MandatoryNumberCriterionOption(messageID ?? value, value, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DurationCriterion extends Criterion<INumberValue> {
|
export class DurationCriterion extends Criterion<INumberValue> {
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ export function makeCriteria(type: CriterionType = "none") {
|
|||||||
case "performer_count":
|
case "performer_count":
|
||||||
case "performer_age":
|
case "performer_age":
|
||||||
case "tag_count":
|
case "tag_count":
|
||||||
|
case "file_count":
|
||||||
return new NumberCriterion(
|
return new NumberCriterion(
|
||||||
new MandatoryNumberCriterionOption(type, type)
|
new MandatoryNumberCriterionOption(type, type)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ const sortByOptions = ["date", ...MediaSortByOptions]
|
|||||||
messageID: "image_count",
|
messageID: "image_count",
|
||||||
value: "images_count",
|
value: "images_count",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
messageID: "zip_file_count",
|
||||||
|
value: "file_count",
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const displayModeOptions = [
|
const displayModeOptions = [
|
||||||
@@ -56,6 +60,7 @@ const criterionOptions = [
|
|||||||
createStringCriterionOption("image_count"),
|
createStringCriterionOption("image_count"),
|
||||||
StudiosCriterionOption,
|
StudiosCriterionOption,
|
||||||
createStringCriterionOption("url"),
|
createStringCriterionOption("url"),
|
||||||
|
createMandatoryNumberCriterionOption("file_count", "zip_file_count"),
|
||||||
];
|
];
|
||||||
|
|
||||||
export const GalleryListFilterOptions = new ListFilterOptions(
|
export const GalleryListFilterOptions = new ListFilterOptions(
|
||||||
|
|||||||
@@ -19,9 +19,12 @@ import { DisplayMode } from "./types";
|
|||||||
|
|
||||||
const defaultSortBy = "path";
|
const defaultSortBy = "path";
|
||||||
|
|
||||||
const sortByOptions = ["o_counter", "filesize", ...MediaSortByOptions].map(
|
const sortByOptions = [
|
||||||
ListFilterOptions.createSortBy
|
"o_counter",
|
||||||
);
|
"filesize",
|
||||||
|
"file_count",
|
||||||
|
...MediaSortByOptions,
|
||||||
|
].map(ListFilterOptions.createSortBy);
|
||||||
|
|
||||||
const displayModeOptions = [DisplayMode.Grid, DisplayMode.Wall];
|
const displayModeOptions = [DisplayMode.Grid, DisplayMode.Wall];
|
||||||
const criterionOptions = [
|
const criterionOptions = [
|
||||||
@@ -41,6 +44,7 @@ const criterionOptions = [
|
|||||||
createMandatoryNumberCriterionOption("performer_age"),
|
createMandatoryNumberCriterionOption("performer_age"),
|
||||||
PerformerFavoriteCriterionOption,
|
PerformerFavoriteCriterionOption,
|
||||||
StudiosCriterionOption,
|
StudiosCriterionOption,
|
||||||
|
createMandatoryNumberCriterionOption("file_count"),
|
||||||
];
|
];
|
||||||
export const ImageListFilterOptions = new ListFilterOptions(
|
export const ImageListFilterOptions = new ListFilterOptions(
|
||||||
defaultSortBy,
|
defaultSortBy,
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const sortByOptions = [
|
|||||||
"organized",
|
"organized",
|
||||||
"o_counter",
|
"o_counter",
|
||||||
"date",
|
"date",
|
||||||
|
"file_count",
|
||||||
"filesize",
|
"filesize",
|
||||||
"duration",
|
"duration",
|
||||||
"framerate",
|
"framerate",
|
||||||
@@ -81,6 +82,7 @@ const criterionOptions = [
|
|||||||
InteractiveCriterionOption,
|
InteractiveCriterionOption,
|
||||||
CaptionsCriterionOption,
|
CaptionsCriterionOption,
|
||||||
createMandatoryNumberCriterionOption("interactive_speed"),
|
createMandatoryNumberCriterionOption("interactive_speed"),
|
||||||
|
createMandatoryNumberCriterionOption("file_count"),
|
||||||
];
|
];
|
||||||
|
|
||||||
export const SceneListFilterOptions = new ListFilterOptions(
|
export const SceneListFilterOptions = new ListFilterOptions(
|
||||||
|
|||||||
@@ -133,4 +133,5 @@ export type CriterionType =
|
|||||||
| "performer_favorite"
|
| "performer_favorite"
|
||||||
| "performer_age"
|
| "performer_age"
|
||||||
| "duplicated"
|
| "duplicated"
|
||||||
| "ignore_auto_tag";
|
| "ignore_auto_tag"
|
||||||
|
| "file_count";
|
||||||
|
|||||||
Reference in New Issue
Block a user