Change performer height to be numeric (#3060)

* Make height an int. Add height_cm field
* Change UI to use height_cm
* Use number fields for height/weight
* Add migration note
This commit is contained in:
WithoutPants
2022-11-08 14:09:03 +11:00
committed by GitHub
parent b9e07ade92
commit d2743cf5fb
35 changed files with 432 additions and 99 deletions

View File

@@ -71,11 +71,11 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
);
}
const formatHeight = (height?: string | null) => {
const formatHeight = (height?: number | null) => {
if (!height) {
return "";
}
return intl.formatNumber(Number.parseInt(height, 10), {
return intl.formatNumber(height, {
style: "unit",
unit: "centimeter",
unitDisplay: "narrow",
@@ -120,7 +120,7 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
getCountryByISO(performer.country, intl.locale) ?? performer.country
}
/>
<TextField id="height" value={formatHeight(performer.height)} />
<TextField id="height" value={formatHeight(performer.height_cm)} />
<TextField id="weight" value={formatWeight(performer.weight)} />
<TextField id="measurements" value={performer.measurements} />
<TextField id="fake_tits" value={performer.fake_tits} />

View File

@@ -106,7 +106,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
ethnicity: yup.string().optional(),
eye_color: yup.string().optional(),
country: yup.string().optional(),
height: yup.string().optional(),
height_cm: yup.number().optional(),
measurements: yup.string().optional(),
fake_tits: yup.string().optional(),
career_length: yup.string().optional(),
@@ -133,7 +133,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
ethnicity: performer.ethnicity ?? "",
eye_color: performer.eye_color ?? "",
country: performer.country ?? "",
height: performer.height ?? "",
height_cm: performer.height_cm ?? undefined,
measurements: performer.measurements ?? "",
fake_tits: performer.fake_tits ?? "",
career_length: performer.career_length ?? "",
@@ -279,7 +279,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
formik.setFieldValue("eye_color", state.eye_color);
}
if (state.height) {
formik.setFieldValue("height", state.height);
formik.setFieldValue("height_cm", parseInt(state.height, 10));
}
if (state.measurements) {
formik.setFieldValue("measurements", state.measurements);
@@ -445,7 +445,8 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
return {
...values,
gender: stringToGender(values.gender) ?? null,
weight: Number(values.weight),
height_cm: values.height_cm ? Number(values.height_cm) : null,
weight: values.weight ? Number(values.weight) : null,
id: performer.id ?? "",
};
}
@@ -454,7 +455,8 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
return {
...values,
gender: stringToGender(values.gender),
weight: Number(values.weight),
height_cm: values.height_cm ? Number(values.height_cm) : null,
weight: values.weight ? Number(values.weight) : null,
};
}
@@ -797,16 +799,26 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
);
}
function renderTextField(field: string, title: string, placeholder?: string) {
function renderField(
field: string,
props?: {
messageID?: string;
placeholder?: string;
type?: string;
}
) {
const title = intl.formatMessage({ id: props?.messageID ?? field });
return (
<Form.Group controlId={field} as={Row}>
<Form.Label column xs={labelXS} xl={labelXL}>
<FormattedMessage id={field} defaultMessage={title} />
{title}
</Form.Label>
<Col xs={fieldXS} xl={fieldXL}>
<Form.Control
type={props?.type ?? "text"}
className="text-input"
placeholder={placeholder ?? title}
placeholder={props?.placeholder ?? title}
{...formik.getFieldProps(field)}
isInvalid={!!formik.getFieldMeta(field).error}
/>
@@ -877,8 +889,8 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
</Col>
</Form.Group>
{renderTextField("birthdate", "Birthdate", "YYYY-MM-DD")}
{renderTextField("death_date", "Death Date", "YYYY-MM-DD")}
{renderField("birthdate", { placeholder: "YYYY-MM-DD" })}
{renderField("death_date", { placeholder: "YYYY-MM-DD" })}
<Form.Group as={Row}>
<Form.Label column xs={labelXS} xl={labelXL}>
@@ -892,13 +904,20 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
</Col>
</Form.Group>
{renderTextField("ethnicity", "Ethnicity")}
{renderTextField("hair_color", "Hair Color")}
{renderTextField("eye_color", "Eye Color")}
{renderTextField("height", "Height (cm)")}
{renderTextField("weight", "Weight (kg)")}
{renderTextField("measurements", "Measurements")}
{renderTextField("fake_tits", "Fake Tits")}
{renderField("ethnicity")}
{renderField("hair_color")}
{renderField("eye_color")}
{renderField("height_cm", {
type: "number",
messageID: "height",
placeholder: intl.formatMessage({ id: "height_cm" }),
})}
{renderField("weight", {
type: "number",
placeholder: intl.formatMessage({ id: "weight_kg" }),
})}
{renderField("measurements")}
{renderField("fake_tits")}
<Form.Group controlId="tattoos" as={Row}>
<Form.Label column sm={labelXS} xl={labelXL}>
@@ -928,7 +947,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
</Col>
</Form.Group>
{renderTextField("career_length", "Career Length")}
{renderField("career_length")}
<Form.Group controlId="url" as={Row}>
<Form.Label column xs={labelXS} xl={labelXL}>
@@ -943,8 +962,8 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
</Col>
</Form.Group>
{renderTextField("twitter", "Twitter")}
{renderTextField("instagram", "Instagram")}
{renderField("twitter")}
{renderField("instagram")}
<Form.Group controlId="details" as={Row}>
<Form.Label column sm={labelXS} xl={labelXL}>
<FormattedMessage id="details" />

View File

@@ -196,7 +196,10 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
new ScrapeResult<string>(props.performer.eye_color, props.scraped.eye_color)
);
const [height, setHeight] = useState<ScrapeResult<string>>(
new ScrapeResult<string>(props.performer.height, props.scraped.height)
new ScrapeResult<string>(
props.performer.height_cm?.toString(),
props.scraped.height
)
);
const [weight, setWeight] = useState<ScrapeResult<string>>(
new ScrapeResult<string>(

View File

@@ -58,7 +58,7 @@ export const PerformerListTable: React.FC<IPerformerListTableProps> = (
</Link>
</td>
<td>{performer.birthdate}</td>
<td>{performer.height}</td>
<td>{performer.height_cm}</td>
</tr>
);

View File

@@ -133,7 +133,7 @@ const PerformerModal: React.FC<IPerformerModalProps> = ({
ethnicity: performer.ethnicity,
eye_color: performer.eye_color,
country: performer.country,
height: performer.height,
height_cm: Number.parseFloat(performer.height ?? "") ?? undefined,
measurements: performer.measurements,
fake_tits: performer.fake_tits,
career_length: performer.career_length,
@@ -153,6 +153,10 @@ const PerformerModal: React.FC<IPerformerModalProps> = ({
performerData.weight = undefined;
}
if (Number.isNaN(performerData.height ?? 0)) {
performerData.height = undefined;
}
if (performer.tags) {
performerData.tag_ids = performer.tags
.map((t) => t.stored_id)

View File

@@ -1194,7 +1194,7 @@ export const makePerformerCreateInput = (toCreate: GQL.ScrapedPerformer) => {
ethnicity: toCreate.ethnicity,
country: toCreate.country,
eye_color: toCreate.eye_color,
height: toCreate.height,
height_cm: toCreate.height ? Number(toCreate.height) : undefined,
measurements: toCreate.measurements,
fake_tits: toCreate.fake_tits,
career_length: toCreate.career_length,

View File

@@ -3,5 +3,11 @@
* Added selector for Country field. ([#1922](https://github.com/stashapp/stash/pull/1922))
* Added tag description filter criterion. ([#3011](https://github.com/stashapp/stash/pull/3011))
### 🎨 Improvements
* Changed Performer height to be numeric, and changed filtering accordingly. ((#3060)[https://github.com/stashapp/stash/pull/3060])
### 🐛 Bug fixes
* Scene Player no longer always resumes playing when seeking. ([#3020](https://github.com/stashapp/stash/pull/3020))
* Fixed space bar sometimes no playing/pausing the scene player. ([#3020](https://github.com/stashapp/stash/pull/3020))
* Fixed scrubber thumbnails not disappearing when seeking on mobile. ([#3020](https://github.com/stashapp/stash/pull/3020))
* Fix path filter behaviour to be consistent with previous behaviour. ([#3041](https://github.com/stashapp/stash/pull/3041))

View File

@@ -0,0 +1 @@
This migration changes performer height values from strings to numbers. Non-numeric performer height values **will be erased during this migration**.

View File

@@ -1,7 +1,9 @@
import migration32 from "./32.md";
import migration38 from "./38.md";
type Module = typeof migration32;
export const migrationNotes: Record<number, Module> = {
32: migration32,
38: migration38,
};

View File

@@ -807,6 +807,7 @@
},
"hasMarkers": "Has Markers",
"height": "Height",
"height_cm": "Height (cm)",
"help": "Help",
"ignore_auto_tag": "Ignore Auto Tag",
"image": "Image",
@@ -1065,6 +1066,7 @@
"videos": "Videos",
"view_all": "View All",
"weight": "Weight",
"weight_kg": "Weight (kg)",
"years_old": "years old",
"zip_file_count": "Zip File Count"
}

View File

@@ -147,10 +147,14 @@ export function makeCriteria(type: CriterionType = "none") {
return new DuplicatedCriterion();
case "country":
return new CountryCriterion();
case "height":
case "height_cm":
return new NumberCriterion(
new NumberCriterionOption("height", "height_cm", type)
);
case "ethnicity":
case "hair_color":
case "eye_color":
case "height":
case "measurements":
case "fake_tits":
case "career_length":

View File

@@ -3,6 +3,7 @@ import {
createMandatoryNumberCriterionOption,
createStringCriterionOption,
createBooleanCriterionOption,
NumberCriterionOption,
} from "./criteria/criterion";
import { FavoriteCriterionOption } from "./criteria/favorite";
import { GenderCriterionOption } from "./criteria/gender";
@@ -58,7 +59,6 @@ const stringCriteria: CriterionType[] = [
"country",
"hair_color",
"eye_color",
"height",
"measurements",
"fake_tits",
"career_length",
@@ -81,6 +81,7 @@ const criterionOptions = [
createMandatoryNumberCriterionOption("image_count"),
createMandatoryNumberCriterionOption("gallery_count"),
createBooleanCriterionOption("ignore_auto_tag"),
new NumberCriterionOption("height", "height_cm", "height_cm"),
...numberCriteria.map((c) => createNumberCriterionOption(c)),
...stringCriteria.map((c) => createStringCriterionOption(c)),
];

View File

@@ -88,6 +88,7 @@ export type CriterionType =
| "hair_color"
| "eye_color"
| "height"
| "height_cm"
| "weight"
| "measurements"
| "fake_tits"