mirror of
https://github.com/stashapp/stash.git
synced 2025-12-07 17:02:38 +01:00
Fix tag display issue in performer scrape dialog (#4943)
This commit is contained in:
parent
4b8af18fab
commit
dbfa450ace
2 changed files with 34 additions and 150 deletions
|
|
@ -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) => {
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue