Fix tag display issue in performer scrape dialog (#4943)

This commit is contained in:
WithoutPants 2024-06-07 14:42:48 +10:00 committed by GitHub
parent 4b8af18fab
commit dbfa450ace
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 34 additions and 150 deletions

View file

@ -597,6 +597,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
return ( return (
<PerformerScrapeDialog <PerformerScrapeDialog
performer={currentPerformer} performer={currentPerformer}
performerTags={tags}
scraped={scrapedPerformer} scraped={scrapedPerformer}
scraper={scraper} scraper={scraper}
onClose={(p) => { onClose={(p) => {

View file

@ -9,11 +9,7 @@ import {
ScrapedTextAreaRow, ScrapedTextAreaRow,
ScrapedCountryRow, ScrapedCountryRow,
} from "src/components/Shared/ScrapeDialog/ScrapeDialog"; } from "src/components/Shared/ScrapeDialog/ScrapeDialog";
import { useTagCreate } from "src/core/StashService";
import { Form } from "react-bootstrap"; import { Form } from "react-bootstrap";
import { TagSelect } from "src/components/Shared/Select";
import { useToast } from "src/hooks/Toast";
import clone from "lodash-es/clone";
import { import {
genderStrings, genderStrings,
genderToString, genderToString,
@ -25,7 +21,14 @@ import {
stringToCircumcised, stringToCircumcised,
} from "src/utils/circumcised"; } from "src/utils/circumcised";
import { IStashBox } from "./PerformerStashBoxModal"; import { IStashBox } from "./PerformerStashBoxModal";
import { ScrapeResult } from "src/components/Shared/ScrapeDialog/scrapeResult"; import {
ObjectListScrapeResult,
ScrapeResult,
} from "src/components/Shared/ScrapeDialog/scrapeResult";
import { ScrapedTagsRow } from "src/components/Shared/ScrapeDialog/ScrapedObjectsRow";
import { sortStoredIdObjects } from "src/utils/data";
import { Tag } from "src/components/Tags/TagSelect";
import { useCreateScrapedTag } from "src/components/Shared/ScrapeDialog/createObjects";
function renderScrapedGender( function renderScrapedGender(
result: ScrapeResult<string>, result: ScrapeResult<string>,
@ -76,55 +79,6 @@ function renderScrapedGenderRow(
); );
} }
function renderScrapedTags(
result: ScrapeResult<string[]>,
isNew?: boolean,
onChange?: (value: string[]) => void
) {
const resultValue = isNew ? result.newValue : result.originalValue;
const value = resultValue ?? [];
return (
<TagSelect
isMulti
className="form-control react-select"
isDisabled={!isNew}
onSelect={(items) => {
if (onChange) {
onChange(items.map((i) => i.id));
}
}}
ids={value}
/>
);
}
function renderScrapedTagsRow(
title: string,
result: ScrapeResult<string[]>,
onChange: (value: ScrapeResult<string[]>) => void,
newTags: GQL.ScrapedTag[],
onCreateNew?: (value: GQL.ScrapedTag) => void
) {
return (
<ScrapeDialogRow
title={title}
result={result}
renderOriginalField={() => renderScrapedTags(result)}
renderNewField={() =>
renderScrapedTags(result, true, (value) =>
onChange(result.cloneWithValue(value))
)
}
newValues={newTags}
onChange={onChange}
onCreateNew={(i) => {
if (onCreateNew) onCreateNew(newTags[i]);
}}
/>
);
}
function renderScrapedCircumcised( function renderScrapedCircumcised(
result: ScrapeResult<string>, result: ScrapeResult<string>,
isNew?: boolean, isNew?: boolean,
@ -176,6 +130,7 @@ function renderScrapedCircumcisedRow(
interface IPerformerScrapeDialogProps { interface IPerformerScrapeDialogProps {
performer: Partial<GQL.PerformerUpdateInput>; performer: Partial<GQL.PerformerUpdateInput>;
performerTags: Tag[];
scraped: GQL.ScrapedPerformer; scraped: GQL.ScrapedPerformer;
scraper?: GQL.Scraper | IStashBox; scraper?: GQL.Scraper | IStashBox;
@ -349,55 +304,15 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
) )
); );
const [createTag] = useTagCreate(); const [tags, setTags] = useState<ObjectListScrapeResult<GQL.ScrapedTag>>(
const Toast = useToast(); new ObjectListScrapeResult<GQL.ScrapedTag>(
sortStoredIdObjects(
interface IHasStoredID { props.performerTags.map((t) => ({
stored_id?: string | null; stored_id: t.id,
} name: t.name,
}))
function mapStoredIdObjects( ),
scrapedObjects?: IHasStoredID[] sortStoredIdObjects(props.scraped.tags ?? undefined)
): string[] | undefined {
if (!scrapedObjects) {
return undefined;
}
const ret = scrapedObjects
.map((p) => p.stored_id)
.filter((p) => {
return p !== undefined && p !== null;
}) as string[];
if (ret.length === 0) {
return undefined;
}
// sort by id numerically
ret.sort((a, b) => {
return parseInt(a, 10) - parseInt(b, 10);
});
return ret;
}
function sortIdList(idList?: string[] | null) {
if (!idList) {
return;
}
const ret = clone(idList);
// sort by id numerically
ret.sort((a, b) => {
return parseInt(a, 10) - parseInt(b, 10);
});
return ret;
}
const [tags, setTags] = useState<ScrapeResult<string[]>>(
new ScrapeResult<string[]>(
sortIdList(props.performer.tag_ids ?? undefined),
mapStoredIdObjects(props.scraped.tags ?? undefined)
) )
); );
@ -405,6 +320,13 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
props.scraped.tags?.filter((t) => !t.stored_id) ?? [] props.scraped.tags?.filter((t) => !t.stored_id) ?? []
); );
const createNewTag = useCreateScrapedTag({
scrapeResult: tags,
setScrapeResult: setTags,
newObjects: newTags,
setNewObjects: setNewTags,
});
const [image, setImage] = useState<ScrapeResult<string>>( const [image, setImage] = useState<ScrapeResult<string>>(
new ScrapeResult<string>( new ScrapeResult<string>(
props.performer.image, props.performer.image,
@ -453,40 +375,6 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
return <></>; return <></>;
} }
async function createNewTag(toCreate: GQL.ScrapedTag) {
const tagInput: GQL.TagCreateInput = { name: toCreate.name ?? "" };
try {
const result = await createTag({
variables: {
input: tagInput,
},
});
// add the new tag to the new tags value
const tagClone = tags.cloneWithValue(tags.newValue);
if (!tagClone.newValue) {
tagClone.newValue = [];
}
tagClone.newValue.push(result.data!.tagCreate!.id);
setTags(tagClone);
// remove the tag from the list
const newTagsClone = newTags.concat();
const pIndex = newTagsClone.indexOf(toCreate);
newTagsClone.splice(pIndex, 1);
setNewTags(newTagsClone);
Toast.success(
<span>
Created tag: <b>{toCreate.name}</b>
</span>
);
} catch (e) {
Toast.error(e);
}
}
function makeNewScrapedItem(): GQL.ScrapedPerformer { function makeNewScrapedItem(): GQL.ScrapedPerformer {
const newImage = image.getNewValue(); const newImage = image.getNewValue();
return { return {
@ -507,12 +395,7 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
twitter: twitter.getNewValue(), twitter: twitter.getNewValue(),
instagram: instagram.getNewValue(), instagram: instagram.getNewValue(),
gender: gender.getNewValue(), gender: gender.getNewValue(),
tags: tags.getNewValue()?.map((m) => { tags: tags.getNewValue(),
return {
stored_id: m,
name: "",
};
}),
images: newImage ? [newImage] : undefined, images: newImage ? [newImage] : undefined,
details: details.getNewValue(), details: details.getNewValue(),
death_date: deathDate.getNewValue(), death_date: deathDate.getNewValue(),
@ -642,13 +525,13 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
result={details} result={details}
onChange={(value) => setDetails(value)} onChange={(value) => setDetails(value)}
/> />
{renderScrapedTagsRow( <ScrapedTagsRow
intl.formatMessage({ id: "tags" }), title={intl.formatMessage({ id: "tags" })}
tags, result={tags}
(value) => setTags(value), onChange={(value) => setTags(value)}
newTags, newObjects={newTags}
createNewTag onCreateNew={createNewTag}
)} />
<ScrapedImagesRow <ScrapedImagesRow
title={intl.formatMessage({ id: "performer_image" })} title={intl.formatMessage({ id: "performer_image" })}
className="performer-image" className="performer-image"