Performer select calculated ages (#5110)

* Change wording of performer age at production

The Performer card had "x years old in this scene", regardless of what sort of media it was attached to. I have made both strings "x [years old] at production instead.
---------
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
dogwithakeyboard
2025-03-05 02:30:59 +00:00
committed by GitHub
parent cbcc1994e8
commit df5566771a
12 changed files with 85 additions and 14 deletions

View File

@@ -364,9 +364,22 @@ export const GalleryEditPanel: React.FC<IProps> = ({
} }
function renderPerformersField() { function renderPerformersField() {
const date = (() => {
try {
return schema.validateSyncAt("date", formik.values);
} catch (e) {
return undefined;
}
})();
const title = intl.formatMessage({ id: "performers" }); const title = intl.formatMessage({ id: "performers" });
const control = ( const control = (
<PerformerSelect isMulti onSelect={onSetPerformers} values={performers} /> <PerformerSelect
isMulti
onSelect={onSetPerformers}
values={performers}
ageFromDate={date}
/>
); );
return renderField("performer_ids", title, control, fullWidthProps); return renderField("performer_ids", title, control, fullWidthProps);

View File

@@ -199,6 +199,7 @@ export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = ({
onChange={(value) => setPerformers(value)} onChange={(value) => setPerformers(value)}
newObjects={newPerformers} newObjects={newPerformers}
onCreateNew={createNewPerformer} onCreateNew={createNewPerformer}
ageFromDate={date.useNewValue ? date.newValue : date.originalValue}
/> />
{scrapedTagsRow} {scrapedTagsRow}
<ScrapedTextAreaRow <ScrapedTextAreaRow

View File

@@ -350,9 +350,22 @@ export const ImageEditPanel: React.FC<IProps> = ({
} }
function renderPerformersField() { function renderPerformersField() {
const date = (() => {
try {
return schema.validateSyncAt("date", formik.values);
} catch (e) {
return undefined;
}
})();
const title = intl.formatMessage({ id: "performers" }); const title = intl.formatMessage({ id: "performers" });
const control = ( const control = (
<PerformerSelect isMulti onSelect={onSetPerformers} values={performers} /> <PerformerSelect
isMulti
onSelect={onSetPerformers}
values={performers}
ageFromDate={date}
/>
); );
return renderField("performer_ids", title, control, fullWidthProps); return renderField("performer_ids", title, control, fullWidthProps);

View File

@@ -71,7 +71,7 @@ const performerSelectSort = PatchFunction(
); );
const _PerformerSelect: React.FC< const _PerformerSelect: React.FC<
IFilterProps & IFilterValueProps<Performer> IFilterProps & IFilterValueProps<Performer> & { ageFromDate?: string | null }
> = (props) => { > = (props) => {
const [createPerformer] = usePerformerCreate(); const [createPerformer] = usePerformerCreate();
@@ -117,6 +117,27 @@ const _PerformerSelect: React.FC<
); );
} }
const sceneAge = TextUtils.age(object.birthdate, props.ageFromDate);
const age =
sceneAge < 18
? TextUtils.age(object.birthdate, object.death_date)
: sceneAge;
const ageL10nId =
!props.ageFromDate || sceneAge < 18
? "media_info.performer_card.age"
: "age_on_date";
const ageL10String = intl.formatMessage({
id: "years_old",
defaultMessage: "years old",
});
const ageString = intl.formatMessage(
{ id: ageL10nId },
{ age, years_old: ageL10String }
);
thisOptionProps = { thisOptionProps = {
...optionProps, ...optionProps,
children: ( children: (
@@ -156,12 +177,10 @@ const _PerformerSelect: React.FC<
)} )}
{object.birthdate && ( {object.birthdate && (
<span className="performer-select-birthdate">{`${ <span className="performer-select-birthdate">
object.birthdate {object.birthdate}
} (${TextUtils.age( <span className="performer-select-age">{` (${ageString})`}</span>
object.birthdate, </span>
object.death_date
)})`}</span>
)} )}
</span> </span>
</span> </span>

View File

@@ -625,9 +625,22 @@ export const SceneEditPanel: React.FC<IProps> = ({
} }
function renderPerformersField() { function renderPerformersField() {
const date = (() => {
try {
return schema.validateSyncAt("date", formik.values);
} catch (e) {
return undefined;
}
})();
const title = intl.formatMessage({ id: "performers" }); const title = intl.formatMessage({ id: "performers" });
const control = ( const control = (
<PerformerSelect isMulti onSelect={onSetPerformers} values={performers} /> <PerformerSelect
isMulti
onSelect={onSetPerformers}
values={performers}
ageFromDate={date}
/>
); );
return renderField("performer_ids", title, control, fullWidthProps); return renderField("performer_ids", title, control, fullWidthProps);

View File

@@ -252,6 +252,7 @@ export const SceneScrapeDialog: React.FC<ISceneScrapeDialogProps> = ({
onChange={(value) => setPerformers(value)} onChange={(value) => setPerformers(value)}
newObjects={newPerformers} newObjects={newPerformers}
onCreateNew={createNewPerformer} onCreateNew={createNewPerformer}
ageFromDate={date.useNewValue ? date.newValue : date.originalValue}
/> />
<ScrapedGroupsRow <ScrapedGroupsRow
title={intl.formatMessage({ id: "groups" })} title={intl.formatMessage({ id: "groups" })}

View File

@@ -507,6 +507,7 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
title={intl.formatMessage({ id: "performers" })} title={intl.formatMessage({ id: "performers" })}
result={performers} result={performers}
onChange={(value) => setPerformers(value)} onChange={(value) => setPerformers(value)}
ageFromDate={date.useNewValue ? date.newValue : date.originalValue}
/> />
<ScrapedGroupsRow <ScrapedGroupsRow
title={intl.formatMessage({ id: "groups" })} title={intl.formatMessage({ id: "groups" })}

View File

@@ -137,8 +137,8 @@ type IScrapedObjectRowImpl<T> = Omit<
>; >;
export const ScrapedPerformersRow: React.FC< export const ScrapedPerformersRow: React.FC<
IScrapedObjectRowImpl<GQL.ScrapedPerformer> IScrapedObjectRowImpl<GQL.ScrapedPerformer> & { ageFromDate?: string | null }
> = ({ title, result, onChange, newObjects, onCreateNew }) => { > = ({ title, result, onChange, newObjects, onCreateNew, ageFromDate }) => {
const performersCopy = useMemo(() => { const performersCopy = useMemo(() => {
return ( return (
newObjects?.map((p) => { newObjects?.map((p) => {
@@ -179,6 +179,7 @@ export const ScrapedPerformersRow: React.FC<
} }
}} }}
values={selectValue} values={selectValue}
ageFromDate={ageFromDate}
/> />
); );
} }

View File

@@ -51,6 +51,7 @@ interface IPerformerResultProps {
onCreate: () => void; onCreate: () => void;
onLink?: () => Promise<void>; onLink?: () => Promise<void>;
endpoint?: string; endpoint?: string;
ageFromDate?: string | null;
} }
const PerformerResult: React.FC<IPerformerResultProps> = ({ const PerformerResult: React.FC<IPerformerResultProps> = ({
@@ -60,6 +61,7 @@ const PerformerResult: React.FC<IPerformerResultProps> = ({
onCreate, onCreate,
onLink, onLink,
endpoint, endpoint,
ageFromDate,
}) => { }) => {
const { data: performerData, loading: stashLoading } = const { data: performerData, loading: stashLoading } =
GQL.useFindPerformerQuery({ GQL.useFindPerformerQuery({
@@ -189,6 +191,7 @@ const PerformerResult: React.FC<IPerformerResultProps> = ({
onSelect={handleSelect} onSelect={handleSelect}
active={selectedSource === "existing"} active={selectedSource === "existing"}
isClearable={false} isClearable={false}
ageFromDate={ageFromDate}
/> />
{maybeRenderLinkButton()} {maybeRenderLinkButton()}
</ButtonGroup> </ButtonGroup>

View File

@@ -701,6 +701,11 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
currentSource?.sourceInput.stash_box_endpoint ?? undefined currentSource?.sourceInput.stash_box_endpoint ?? undefined
} }
key={`${performer.name ?? performer.remote_site_id ?? ""}`} key={`${performer.name ?? performer.remote_site_id ?? ""}`}
ageFromDate={
!scene.date || excludedFields.date
? stashScene.date
: scene.date
}
/> />
))} ))}
</Form.Group> </Form.Group>

View File

@@ -67,7 +67,7 @@
.performer-select, .performer-select,
.studio-select { .studio-select {
width: 14rem; width: 18rem;
// stylelint-disable-next-line selector-class-pattern // stylelint-disable-next-line selector-class-pattern
&-active .react-select__control { &-active .react-select__control {

View File

@@ -145,6 +145,7 @@
}, },
"actions_name": "Actions", "actions_name": "Actions",
"age": "Age", "age": "Age",
"age_on_date": "{age} at production",
"aliases": "Aliases", "aliases": "Aliases",
"all": "all", "all": "all",
"also_known_as": "Also known as", "also_known_as": "Also known as",
@@ -1151,7 +1152,7 @@
"o_count": "O Count", "o_count": "O Count",
"performer_card": { "performer_card": {
"age": "{age} {years_old}", "age": "{age} {years_old}",
"age_context": "{age} {years_old} in this scene" "age_context": "{age} {years_old} at production"
}, },
"phash": "PHash", "phash": "PHash",
"play_count": "Play Count", "play_count": "Play Count",