mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 08:26:00 +01:00
merge sorting + add URLs
This commit is contained in:
parent
e0de8e7c7c
commit
e057b2899b
8 changed files with 56 additions and 0 deletions
|
|
@ -89,6 +89,10 @@ input TitleDuplicationCriterionInput {
|
||||||
duplicated: Boolean
|
duplicated: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input URLDuplicationCriterionInput {
|
||||||
|
duplicated: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
input StashIDCriterionInput {
|
input StashIDCriterionInput {
|
||||||
"""
|
"""
|
||||||
If present, this value is treated as a predicate.
|
If present, this value is treated as a predicate.
|
||||||
|
|
@ -262,6 +266,8 @@ input SceneFilterType {
|
||||||
duplicated_stash_id: StashIDDuplicationCriterionInput
|
duplicated_stash_id: StashIDDuplicationCriterionInput
|
||||||
"Filter Scenes that have the same title"
|
"Filter Scenes that have the same title"
|
||||||
duplicated_title: TitleDuplicationCriterionInput
|
duplicated_title: TitleDuplicationCriterionInput
|
||||||
|
"Filter Scenes that have the same URL"
|
||||||
|
duplicated_url: URLDuplicationCriterionInput
|
||||||
"Filter by resolution"
|
"Filter by resolution"
|
||||||
resolution: ResolutionCriterionInput
|
resolution: ResolutionCriterionInput
|
||||||
"Filter by orientation"
|
"Filter by orientation"
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,10 @@ type TitleDuplicationCriterionInput struct {
|
||||||
Duplicated *bool `json:"duplicated"`
|
Duplicated *bool `json:"duplicated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type URLDuplicationCriterionInput struct {
|
||||||
|
Duplicated *bool `json:"duplicated"`
|
||||||
|
}
|
||||||
|
|
||||||
type SceneFilterType struct {
|
type SceneFilterType struct {
|
||||||
OperatorFilter[SceneFilterType]
|
OperatorFilter[SceneFilterType]
|
||||||
ID *IntCriterionInput `json:"id"`
|
ID *IntCriterionInput `json:"id"`
|
||||||
|
|
@ -47,6 +51,8 @@ type SceneFilterType struct {
|
||||||
DuplicatedStashID *StashIDDuplicationCriterionInput `json:"duplicated_stash_id"`
|
DuplicatedStashID *StashIDDuplicationCriterionInput `json:"duplicated_stash_id"`
|
||||||
// Filter Scenes that have the same title
|
// Filter Scenes that have the same title
|
||||||
DuplicatedTitle *TitleDuplicationCriterionInput `json:"duplicated_title"`
|
DuplicatedTitle *TitleDuplicationCriterionInput `json:"duplicated_title"`
|
||||||
|
// Filter Scenes that have the same URL
|
||||||
|
DuplicatedURL *URLDuplicationCriterionInput `json:"duplicated_url"`
|
||||||
// Filter by resolution
|
// Filter by resolution
|
||||||
Resolution *ResolutionCriterionInput `json:"resolution"`
|
Resolution *ResolutionCriterionInput `json:"resolution"`
|
||||||
// Filter by orientation
|
// Filter by orientation
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,7 @@ func (qb *sceneFilterHandler) criterionHandler() criterionHandler {
|
||||||
qb.phashDuplicatedCriterionHandler(sceneFilter.Duplicated, qb.addSceneFilesTable),
|
qb.phashDuplicatedCriterionHandler(sceneFilter.Duplicated, qb.addSceneFilesTable),
|
||||||
qb.stashIDDuplicatedCriterionHandler(sceneFilter.DuplicatedStashID),
|
qb.stashIDDuplicatedCriterionHandler(sceneFilter.DuplicatedStashID),
|
||||||
qb.titleDuplicatedCriterionHandler(sceneFilter.DuplicatedTitle),
|
qb.titleDuplicatedCriterionHandler(sceneFilter.DuplicatedTitle),
|
||||||
|
qb.urlDuplicatedCriterionHandler(sceneFilter.DuplicatedURL),
|
||||||
&dateCriterionHandler{sceneFilter.Date, "scenes.date", nil},
|
&dateCriterionHandler{sceneFilter.Date, "scenes.date", nil},
|
||||||
×tampCriterionHandler{sceneFilter.CreatedAt, "scenes.created_at", nil},
|
×tampCriterionHandler{sceneFilter.CreatedAt, "scenes.created_at", nil},
|
||||||
×tampCriterionHandler{sceneFilter.UpdatedAt, "scenes.updated_at", nil},
|
×tampCriterionHandler{sceneFilter.UpdatedAt, "scenes.updated_at", nil},
|
||||||
|
|
@ -331,6 +332,22 @@ func (qb *sceneFilterHandler) titleDuplicatedCriterionHandler(duplicatedFilter *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (qb *sceneFilterHandler) urlDuplicatedCriterionHandler(duplicatedFilter *models.URLDuplicationCriterionInput) criterionHandlerFunc {
|
||||||
|
return func(ctx context.Context, f *filterBuilder) {
|
||||||
|
if duplicatedFilter != nil && duplicatedFilter.Duplicated != nil {
|
||||||
|
var v string
|
||||||
|
if *duplicatedFilter.Duplicated {
|
||||||
|
v = ">"
|
||||||
|
} else {
|
||||||
|
v = "="
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find URLs that appear on more than one scene
|
||||||
|
f.addInnerJoin("(SELECT scene_id FROM scene_urls INNER JOIN (SELECT url FROM scene_urls GROUP BY url HAVING COUNT(DISTINCT scene_id) "+v+" 1) dupes ON scene_urls.url = dupes.url)", "scurl", "scenes.id = scurl.scene_id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (qb *sceneFilterHandler) codecCriterionHandler(codec *models.StringCriterionInput, codecColumn string, addJoinFn func(f *filterBuilder)) criterionHandlerFunc {
|
func (qb *sceneFilterHandler) codecCriterionHandler(codec *models.StringCriterionInput, codecColumn string, addJoinFn func(f *filterBuilder)) criterionHandlerFunc {
|
||||||
return func(ctx context.Context, f *filterBuilder) {
|
return func(ctx context.Context, f *filterBuilder) {
|
||||||
if codec != nil {
|
if codec != nil {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { Option, SelectedList } from "./SidebarListFilter";
|
||||||
import { DuplicatedCriterionOption } from "src/models/list-filter/criteria/phash";
|
import { DuplicatedCriterionOption } from "src/models/list-filter/criteria/phash";
|
||||||
import { DuplicatedStashIDCriterionOption } from "src/models/list-filter/criteria/stash-ids";
|
import { DuplicatedStashIDCriterionOption } from "src/models/list-filter/criteria/stash-ids";
|
||||||
import { DuplicatedTitleCriterionOption } from "src/models/list-filter/criteria/title";
|
import { DuplicatedTitleCriterionOption } from "src/models/list-filter/criteria/title";
|
||||||
|
import { DuplicatedURLCriterionOption } from "src/models/list-filter/criteria/url";
|
||||||
import { SidebarSection } from "src/components/Shared/Sidebar";
|
import { SidebarSection } from "src/components/Shared/Sidebar";
|
||||||
import { Icon } from "src/components/Shared/Icon";
|
import { Icon } from "src/components/Shared/Icon";
|
||||||
import { faPlus } from "@fortawesome/free-solid-svg-icons";
|
import { faPlus } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
|
@ -16,6 +17,7 @@ const DUPLICATE_TYPES = {
|
||||||
phash: DuplicatedCriterionOption,
|
phash: DuplicatedCriterionOption,
|
||||||
stash_id: DuplicatedStashIDCriterionOption,
|
stash_id: DuplicatedStashIDCriterionOption,
|
||||||
title: DuplicatedTitleCriterionOption,
|
title: DuplicatedTitleCriterionOption,
|
||||||
|
url: DuplicatedURLCriterionOption,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
type DuplicateTypeId = keyof typeof DUPLICATE_TYPES;
|
type DuplicateTypeId = keyof typeof DUPLICATE_TYPES;
|
||||||
|
|
@ -32,6 +34,7 @@ const DUPLICATE_TYPE_MESSAGE_IDS: Record<DuplicateTypeId, string> = {
|
||||||
phash: "media_info.phash",
|
phash: "media_info.phash",
|
||||||
stash_id: "stash_id",
|
stash_id: "stash_id",
|
||||||
title: "title",
|
title: "title",
|
||||||
|
url: "url",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SidebarDuplicateFilter: React.FC<ISidebarDuplicateFilterProps> = ({
|
export const SidebarDuplicateFilter: React.FC<ISidebarDuplicateFilterProps> = ({
|
||||||
|
|
|
||||||
|
|
@ -1063,6 +1063,7 @@
|
||||||
"duplicated_phash": "Duplicated (pHash)",
|
"duplicated_phash": "Duplicated (pHash)",
|
||||||
"duplicated_stash_id": "Duplicated (Stash ID)",
|
"duplicated_stash_id": "Duplicated (Stash ID)",
|
||||||
"duplicated_title": "Duplicated (Title)",
|
"duplicated_title": "Duplicated (Title)",
|
||||||
|
"duplicated_url": "Duplicated (URL)",
|
||||||
"duration": "Duration",
|
"duration": "Duration",
|
||||||
"effect_filters": {
|
"effect_filters": {
|
||||||
"aspect": "Aspect",
|
"aspect": "Aspect",
|
||||||
|
|
|
||||||
20
ui/v2.5/src/models/list-filter/criteria/url.ts
Normal file
20
ui/v2.5/src/models/list-filter/criteria/url.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { UrlDuplicationCriterionInput } from "src/core/generated-graphql";
|
||||||
|
import { BooleanCriterionOption, StringCriterion } from "./criterion";
|
||||||
|
|
||||||
|
export const DuplicatedURLCriterionOption = new BooleanCriterionOption(
|
||||||
|
"duplicated_url",
|
||||||
|
"duplicated_url",
|
||||||
|
() => new DuplicatedURLCriterion()
|
||||||
|
);
|
||||||
|
|
||||||
|
export class DuplicatedURLCriterion extends StringCriterion {
|
||||||
|
constructor() {
|
||||||
|
super(DuplicatedURLCriterionOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
public toCriterionInput(): UrlDuplicationCriterionInput {
|
||||||
|
return {
|
||||||
|
duplicated: this.value === "true",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -36,6 +36,7 @@ import {
|
||||||
StashIDCriterionOption,
|
StashIDCriterionOption,
|
||||||
} from "./criteria/stash-ids";
|
} from "./criteria/stash-ids";
|
||||||
import { DuplicatedTitleCriterionOption } from "./criteria/title";
|
import { DuplicatedTitleCriterionOption } from "./criteria/title";
|
||||||
|
import { DuplicatedURLCriterionOption } from "./criteria/url";
|
||||||
import { RatingCriterionOption } from "./criteria/rating";
|
import { RatingCriterionOption } from "./criteria/rating";
|
||||||
import { PathCriterionOption } from "./criteria/path";
|
import { PathCriterionOption } from "./criteria/path";
|
||||||
import { OrientationCriterionOption } from "./criteria/orientation";
|
import { OrientationCriterionOption } from "./criteria/orientation";
|
||||||
|
|
@ -106,6 +107,7 @@ const criterionOptions = [
|
||||||
DuplicatedCriterionOption,
|
DuplicatedCriterionOption,
|
||||||
DuplicatedStashIDCriterionOption,
|
DuplicatedStashIDCriterionOption,
|
||||||
DuplicatedTitleCriterionOption,
|
DuplicatedTitleCriterionOption,
|
||||||
|
DuplicatedURLCriterionOption,
|
||||||
OrganizedCriterionOption,
|
OrganizedCriterionOption,
|
||||||
RatingCriterionOption,
|
RatingCriterionOption,
|
||||||
createMandatoryNumberCriterionOption("o_counter", "o_count", {
|
createMandatoryNumberCriterionOption("o_counter", "o_count", {
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,7 @@ export type CriterionType =
|
||||||
| "duplicated"
|
| "duplicated"
|
||||||
| "duplicated_stash_id"
|
| "duplicated_stash_id"
|
||||||
| "duplicated_title"
|
| "duplicated_title"
|
||||||
|
| "duplicated_url"
|
||||||
| "ignore_auto_tag"
|
| "ignore_auto_tag"
|
||||||
| "file_count"
|
| "file_count"
|
||||||
| "stash_id_endpoint"
|
| "stash_id_endpoint"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue