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 (
<PerformerScrapeDialog
performer={currentPerformer}
performerTags={tags}
scraped={scrapedPerformer}
scraper={scraper}
onClose={(p) => {

View File

@ -9,11 +9,7 @@ import {
ScrapedTextAreaRow,
ScrapedCountryRow,
} from "src/components/Shared/ScrapeDialog/ScrapeDialog";
import { useTagCreate } from "src/core/StashService";
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 {
genderStrings,
genderToString,
@ -25,7 +21,14 @@ import {
stringToCircumcised,
} from "src/utils/circumcised";
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(
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(
result: ScrapeResult<string>,
isNew?: boolean,
@ -176,6 +130,7 @@ function renderScrapedCircumcisedRow(
interface IPerformerScrapeDialogProps {
performer: Partial<GQL.PerformerUpdateInput>;
performerTags: Tag[];
scraped: GQL.ScrapedPerformer;
scraper?: GQL.Scraper | IStashBox;
@ -349,55 +304,15 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
)
);
const [createTag] = useTagCreate();
const Toast = useToast();
interface IHasStoredID {
stored_id?: string | null;
}
function mapStoredIdObjects(
scrapedObjects?: IHasStoredID[]
): 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)
const [tags, setTags] = useState<ObjectListScrapeResult<GQL.ScrapedTag>>(
new ObjectListScrapeResult<GQL.ScrapedTag>(
sortStoredIdObjects(
props.performerTags.map((t) => ({
stored_id: t.id,
name: t.name,
}))
),
sortStoredIdObjects(props.scraped.tags ?? undefined)
)
);
@ -405,6 +320,13 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
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>>(
new ScrapeResult<string>(
props.performer.image,
@ -453,40 +375,6 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
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 {
const newImage = image.getNewValue();
return {
@ -507,12 +395,7 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
twitter: twitter.getNewValue(),
instagram: instagram.getNewValue(),
gender: gender.getNewValue(),
tags: tags.getNewValue()?.map((m) => {
return {
stored_id: m,
name: "",
};
}),
tags: tags.getNewValue(),
images: newImage ? [newImage] : undefined,
details: details.getNewValue(),
death_date: deathDate.getNewValue(),
@ -642,13 +525,13 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
result={details}
onChange={(value) => setDetails(value)}
/>
{renderScrapedTagsRow(
intl.formatMessage({ id: "tags" }),
tags,
(value) => setTags(value),
newTags,
createNewTag
)}
<ScrapedTagsRow
title={intl.formatMessage({ id: "tags" })}
result={tags}
onChange={(value) => setTags(value)}
newObjects={newTags}
onCreateNew={createNewTag}
/>
<ScrapedImagesRow
title={intl.formatMessage({ id: "performer_image" })}
className="performer-image"