mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 08:26:00 +01:00
Change show male performers option into list of gender checkboxes (#6321)
This commit is contained in:
parent
e052a431d1
commit
d1ee64d36f
5 changed files with 53 additions and 25 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { ScraperSourceInput } from "src/core/generated-graphql";
|
import { GenderEnum, ScraperSourceInput } from "src/core/generated-graphql";
|
||||||
|
|
||||||
export const STASH_BOX_PREFIX = "stashbox:";
|
export const STASH_BOX_PREFIX = "stashbox:";
|
||||||
export const SCRAPER_PREFIX = "scraper:";
|
export const SCRAPER_PREFIX = "scraper:";
|
||||||
|
|
@ -27,7 +27,6 @@ export const DEFAULT_EXCLUDED_STUDIO_FIELDS = ["name"];
|
||||||
|
|
||||||
export const initialConfig: ITaggerConfig = {
|
export const initialConfig: ITaggerConfig = {
|
||||||
blacklist: DEFAULT_BLACKLIST,
|
blacklist: DEFAULT_BLACKLIST,
|
||||||
showMales: true,
|
|
||||||
mode: "auto",
|
mode: "auto",
|
||||||
setCoverImage: true,
|
setCoverImage: true,
|
||||||
setTags: true,
|
setTags: true,
|
||||||
|
|
@ -43,7 +42,7 @@ export type ParseMode = "auto" | "filename" | "dir" | "path" | "metadata";
|
||||||
export type TagOperation = "merge" | "overwrite";
|
export type TagOperation = "merge" | "overwrite";
|
||||||
export interface ITaggerConfig {
|
export interface ITaggerConfig {
|
||||||
blacklist: string[];
|
blacklist: string[];
|
||||||
showMales: boolean;
|
performerGenders?: GenderEnum[];
|
||||||
mode: ParseMode;
|
mode: ParseMode;
|
||||||
setCoverImage: boolean;
|
setCoverImage: boolean;
|
||||||
setTags: boolean;
|
setTags: boolean;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import { Icon } from "src/components/Shared/Icon";
|
import { Icon } from "src/components/Shared/Icon";
|
||||||
import { ParseMode, TagOperation } from "../constants";
|
import { ParseMode, TagOperation } from "../constants";
|
||||||
import { TaggerStateContext } from "../context";
|
import { TaggerStateContext } from "../context";
|
||||||
|
import { GenderEnum } from "src/core/generated-graphql";
|
||||||
|
import { genderList } from "src/utils/gender";
|
||||||
|
|
||||||
const Blacklist: React.FC<{
|
const Blacklist: React.FC<{
|
||||||
list: string[];
|
list: string[];
|
||||||
|
|
@ -118,6 +120,26 @@ const Config: React.FC<IConfigProps> = ({ show }) => {
|
||||||
const { config, setConfig } = useContext(TaggerStateContext);
|
const { config, setConfig } = useContext(TaggerStateContext);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
|
function renderGenderCheckbox(gender: GenderEnum) {
|
||||||
|
const performerGenders = config.performerGenders || genderList.slice();
|
||||||
|
return (
|
||||||
|
<Form.Check
|
||||||
|
key={gender}
|
||||||
|
label={<FormattedMessage id={`gender_types.${gender}`} />}
|
||||||
|
checked={performerGenders.includes(gender)}
|
||||||
|
onChange={(e) => {
|
||||||
|
const isChecked = e.currentTarget.checked;
|
||||||
|
setConfig({
|
||||||
|
...config,
|
||||||
|
performerGenders: isChecked
|
||||||
|
? [...performerGenders, gender]
|
||||||
|
: performerGenders.filter((g) => g !== gender),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Collapse in={show}>
|
<Collapse in={show}>
|
||||||
<Card>
|
<Card>
|
||||||
|
|
@ -127,18 +149,16 @@ const Config: React.FC<IConfigProps> = ({ show }) => {
|
||||||
</h4>
|
</h4>
|
||||||
<hr className="w-100" />
|
<hr className="w-100" />
|
||||||
<Form className="col-md-6">
|
<Form className="col-md-6">
|
||||||
<Form.Group controlId="tag-males" className="align-items-center">
|
<Form.Group
|
||||||
<Form.Check
|
controlId="performer-genders"
|
||||||
label={
|
className="align-items-center"
|
||||||
<FormattedMessage id="component_tagger.config.show_male_label" />
|
>
|
||||||
}
|
<Form.Label>
|
||||||
checked={config.showMales}
|
<FormattedMessage id="component_tagger.config.performer_genders.heading" />
|
||||||
onChange={(e) =>
|
</Form.Label>
|
||||||
setConfig({ ...config, showMales: e.currentTarget.checked })
|
{genderList.map(renderGenderCheckbox)}
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Form.Text>
|
<Form.Text>
|
||||||
<FormattedMessage id="component_tagger.config.show_male_desc" />
|
<FormattedMessage id="component_tagger.config.performer_genders.description" />
|
||||||
</Form.Text>
|
</Form.Text>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
<Form.Group controlId="set-cover" className="align-items-center">
|
<Form.Group controlId="set-cover" className="align-items-center">
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import { TagSelect } from "src/components/Shared/Select";
|
||||||
import { TruncatedText } from "src/components/Shared/TruncatedText";
|
import { TruncatedText } from "src/components/Shared/TruncatedText";
|
||||||
import { OperationButton } from "src/components/Shared/OperationButton";
|
import { OperationButton } from "src/components/Shared/OperationButton";
|
||||||
import * as FormUtils from "src/utils/form";
|
import * as FormUtils from "src/utils/form";
|
||||||
import { stringToGender } from "src/utils/gender";
|
import { genderList, stringToGender } from "src/utils/gender";
|
||||||
import { IScrapedScene, TaggerStateContext } from "../context";
|
import { IScrapedScene, TaggerStateContext } from "../context";
|
||||||
import { OptionalField } from "../IncludeButton";
|
import { OptionalField } from "../IncludeButton";
|
||||||
import { SceneTaggerModalsState } from "./sceneTaggerModals";
|
import { SceneTaggerModalsState } from "./sceneTaggerModals";
|
||||||
|
|
@ -237,17 +237,15 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
|
||||||
saveScene,
|
saveScene,
|
||||||
} = React.useContext(TaggerStateContext);
|
} = React.useContext(TaggerStateContext);
|
||||||
|
|
||||||
|
const performerGenders = config.performerGenders || genderList;
|
||||||
|
|
||||||
const performers = useMemo(
|
const performers = useMemo(
|
||||||
() =>
|
() =>
|
||||||
scene.performers?.filter((p) => {
|
scene.performers?.filter((p) => {
|
||||||
if (!config.showMales) {
|
const gender = p.gender ? stringToGender(p.gender, true) : undefined;
|
||||||
return (
|
return !gender || performerGenders.includes(gender);
|
||||||
!p.gender || stringToGender(p.gender, true) !== GQL.GenderEnum.Male
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}) ?? [],
|
}) ?? [],
|
||||||
[config, scene]
|
[scene, performerGenders]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { createPerformerModal, createStudioModal } = React.useContext(
|
const { createPerformerModal, createStudioModal } = React.useContext(
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,10 @@
|
||||||
},
|
},
|
||||||
"mark_organized_desc": "Immediately mark the scene as Organized after the Save button is clicked.",
|
"mark_organized_desc": "Immediately mark the scene as Organized after the Save button is clicked.",
|
||||||
"mark_organized_label": "Mark as Organized on save",
|
"mark_organized_label": "Mark as Organized on save",
|
||||||
|
"performer_genders": {
|
||||||
|
"heading": "Performer genders",
|
||||||
|
"description": "Performers with these genders will be shown when tagging scenes."
|
||||||
|
},
|
||||||
"query_mode_auto": "Auto",
|
"query_mode_auto": "Auto",
|
||||||
"query_mode_auto_desc": "Uses metadata if present, or filename",
|
"query_mode_auto_desc": "Uses metadata if present, or filename",
|
||||||
"query_mode_dir": "Dir",
|
"query_mode_dir": "Dir",
|
||||||
|
|
@ -205,8 +209,6 @@
|
||||||
"set_cover_label": "Set scene cover image",
|
"set_cover_label": "Set scene cover image",
|
||||||
"set_tag_desc": "Attach tags to scene, either by overwriting or merging with existing tags on scene.",
|
"set_tag_desc": "Attach tags to scene, either by overwriting or merging with existing tags on scene.",
|
||||||
"set_tag_label": "Set tags",
|
"set_tag_label": "Set tags",
|
||||||
"show_male_desc": "Toggle whether male performers will be available to tag.",
|
|
||||||
"show_male_label": "Show male performers",
|
|
||||||
"source": "Source"
|
"source": "Source"
|
||||||
},
|
},
|
||||||
"noun_query": "Query",
|
"noun_query": "Query",
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,23 @@
|
||||||
import * as GQL from "../core/generated-graphql";
|
import * as GQL from "../core/generated-graphql";
|
||||||
|
|
||||||
export const stringGenderMap = new Map<string, GQL.GenderEnum>([
|
export const stringGenderMap = new Map<string, GQL.GenderEnum>([
|
||||||
["Male", GQL.GenderEnum.Male],
|
|
||||||
["Female", GQL.GenderEnum.Female],
|
["Female", GQL.GenderEnum.Female],
|
||||||
|
["Male", GQL.GenderEnum.Male],
|
||||||
["Transgender Male", GQL.GenderEnum.TransgenderMale],
|
["Transgender Male", GQL.GenderEnum.TransgenderMale],
|
||||||
["Transgender Female", GQL.GenderEnum.TransgenderFemale],
|
["Transgender Female", GQL.GenderEnum.TransgenderFemale],
|
||||||
["Intersex", GQL.GenderEnum.Intersex],
|
["Intersex", GQL.GenderEnum.Intersex],
|
||||||
["Non-Binary", GQL.GenderEnum.NonBinary],
|
["Non-Binary", GQL.GenderEnum.NonBinary],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
export const genderList = [
|
||||||
|
GQL.GenderEnum.Female,
|
||||||
|
GQL.GenderEnum.Male,
|
||||||
|
GQL.GenderEnum.TransgenderFemale,
|
||||||
|
GQL.GenderEnum.TransgenderMale,
|
||||||
|
GQL.GenderEnum.Intersex,
|
||||||
|
GQL.GenderEnum.NonBinary,
|
||||||
|
];
|
||||||
|
|
||||||
export const genderToString = (value?: GQL.GenderEnum | string | null) => {
|
export const genderToString = (value?: GQL.GenderEnum | string | null) => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue